Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 /*
     27  * Copyright 1990 by the Massachusetts Institute of Technology.
     28  * All Rights Reserved.
     29  *
     30  * Export of this software from the United States of America may
     31  *   require a specific license from the United States Government.
     32  *   It is the responsibility of any person or organization contemplating
     33  *   export to obtain such a license before exporting.
     34  *
     35  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
     36  * distribute this software and its documentation for any purpose and
     37  * without fee is hereby granted, provided that the above copyright
     38  * notice appear in all copies and that both that copyright notice and
     39  * this permission notice appear in supporting documentation, and that
     40  * the name of M.I.T. not be used in advertising or publicity pertaining
     41  * to distribution of the software without specific, written prior
     42  * permission.  Furthermore if you modify this software you must label
     43  * your software as modified software and not distribute it in such a
     44  * fashion that it might be confused with the original M.I.T. software.
     45  * M.I.T. makes no representations about the suitability of
     46  * this software for any purpose.  It is provided "as is" without express
     47  * or implied warranty.
     48  *
     49  *
     50  * Initialize a credentials cache.
     51  */
     52 #include <kerberosv5/krb5.h>
     53 #include <kerberosv5/com_err.h>
     54 #include <assert.h>
     55 #include <stdio.h>
     56 #include <syslog.h>
     57 #include <errno.h>
     58 
     59 #include <smbsrv/libsmbns.h>
     60 #include <smbns_krb.h>
     61 
     62 int
     63 smb_kinit(char *principal_name, char *principal_passwd)
     64 {
     65 	krb5_context ctx = NULL;
     66 	krb5_ccache cc = NULL;
     67 	krb5_principal me = NULL;
     68 	krb5_creds my_creds;
     69 	krb5_error_code code;
     70 	const char *errmsg = NULL;
     71 	const char *doing = NULL;
     72 
     73 	assert(principal_name != NULL);
     74 	assert(principal_passwd != NULL);
     75 
     76 	(void) memset(&my_creds, 0, sizeof (my_creds));
     77 
     78 	/*
     79 	 * From this point on, we can goto cleanup because the key variables
     80 	 * are initialized.
     81 	 */
     82 
     83 	code = krb5_init_context(&ctx);
     84 	if (code) {
     85 		doing = "initializing context";
     86 		goto cleanup;
     87 	}
     88 
     89 	code = krb5_cc_default(ctx, &cc);
     90 	if (code != 0) {
     91 		doing = "resolve default credentials cache";
     92 		goto cleanup;
     93 	}
     94 
     95 	/* Use specified name */
     96 	code = krb5_parse_name(ctx, principal_name, &me);
     97 	if (code != 0) {
     98 		doing = "parsing principal name";
     99 		goto cleanup;
    100 	}
    101 
    102 	code = krb5_get_init_creds_password(ctx, &my_creds, me,
    103 	    principal_passwd, NULL, 0, (krb5_deltat)0,
    104 	    NULL, NULL);
    105 	if (code != 0) {
    106 		doing = "getting initial credentials";
    107 
    108 		if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
    109 			errmsg = "Password incorrect";
    110 		}
    111 
    112 		goto cleanup;
    113 	}
    114 
    115 	code = krb5_cc_initialize(ctx, cc, me);
    116 	if (code != 0) {
    117 		doing = "initializing cache";
    118 		goto cleanup;
    119 	}
    120 
    121 	code = krb5_cc_store_cred(ctx, cc, &my_creds);
    122 	if (code != 0) {
    123 		doing = "storing credentials";
    124 		goto cleanup;
    125 	}
    126 
    127 	/* SUCCESS! */
    128 
    129 cleanup:
    130 	if (code != 0) {
    131 		if (errmsg == NULL)
    132 			errmsg = error_message(code);
    133 		syslog(LOG_ERR, "k5_kinit: %s (%s)", doing, errmsg);
    134 	}
    135 
    136 	if (my_creds.client == me) {
    137 		my_creds.client = NULL;
    138 	}
    139 	krb5_free_cred_contents(ctx, &my_creds);
    140 
    141 	if (me)
    142 		krb5_free_principal(ctx, me);
    143 	if (cc)
    144 		(void) krb5_cc_close(ctx, cc);
    145 	if (ctx)
    146 		krb5_free_context(ctx);
    147 
    148 	return (code == 0);
    149 }
    150 
    151 /*
    152  * smb_ccache_init
    153  *
    154  * Creates the directory where the Kerberos ccache file is located
    155  * and set KRB5CCNAME in the environment.
    156  *
    157  * Returns 0 upon succcess.  Otherwise, returns
    158  * -1 if it fails to create the specified directory fails.
    159  * -2 if it fails to set the KRB5CCNAME environment variable.
    160  */
    161 int
    162 smb_ccache_init(char *dir, char *filename)
    163 {
    164 	static char buf[MAXPATHLEN];
    165 
    166 	if ((mkdir(dir, 0700) < 0) && (errno != EEXIST))
    167 		return (-1);
    168 
    169 	(void) snprintf(buf, MAXPATHLEN, "KRB5CCNAME=%s/%s", dir, filename);
    170 	if (putenv(buf) != 0)
    171 		return (-2);
    172 	return (0);
    173 }
    174 
    175 void
    176 smb_ccache_remove(char *path)
    177 {
    178 	if ((remove(path) < 0) && (errno != ENOENT))
    179 		syslog(LOG_ERR, "failed to remove ccache (%s)", path);
    180 }
    181