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