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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
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
smb_kinit(char * principal_name,char * principal_passwd)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 = "smbns_krb: initializing context";
85 goto cleanup;
86 }
87
88 code = krb5_cc_default(ctx, &cc);
89 if (code != 0) {
90 doing = "smbns_krb: 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 = "smbns_krb: 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 = "smbns_krb: getting initial credentials";
106
107 if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
108 errmsg = "smbns_krb: Password incorrect";
109 }
110
111 goto cleanup;
112 }
113
114 code = krb5_cc_initialize(ctx, cc, me);
115 if (code != 0) {
116 doing = "smbns_krb: initializing cache";
117 goto cleanup;
118 }
119
120 code = krb5_cc_store_cred(ctx, cc, &my_creds);
121 if (code != 0) {
122 doing = "smbns_krb: storing credentials";
123 goto cleanup;
124 }
125
126 /* SUCCESS! */
127
128 cleanup:
129 if (code != 0) {
130 if (errmsg == NULL)
131 smb_krb5_log_errmsg(ctx, doing, code);
132 else
133 syslog(LOG_ERR, "%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 * Invoke krb5_get_error_message() to generate a richer error message.
153 */
154 void
smb_krb5_log_errmsg(krb5_context ctx,const char * prefix,krb5_error_code code)155 smb_krb5_log_errmsg(krb5_context ctx, const char *prefix, krb5_error_code code)
156 {
157 const char *msg;
158
159 msg = krb5_get_error_message(ctx, code);
160 syslog(LOG_ERR, "%s (%s)", prefix, msg);
161 krb5_free_error_message(ctx, msg);
162 }
163
164 /*
165 * smb_ccache_init
166 *
167 * Creates the directory where the Kerberos ccache file is located
168 * and set KRB5CCNAME in the environment.
169 *
170 * Returns 0 upon succcess. Otherwise, returns
171 * -1 if it fails to create the specified directory fails.
172 * -2 if it fails to set the KRB5CCNAME environment variable.
173 */
174 int
smb_ccache_init(char * dir,char * filename)175 smb_ccache_init(char *dir, char *filename)
176 {
177 static char buf[MAXPATHLEN];
178
179 if ((mkdir(dir, 0700) < 0) && (errno != EEXIST))
180 return (-1);
181
182 (void) snprintf(buf, MAXPATHLEN, "KRB5CCNAME=%s/%s", dir, filename);
183 if (putenv(buf) != 0)
184 return (-2);
185 return (0);
186 }
187
188 void
smb_ccache_remove(char * path)189 smb_ccache_remove(char *path)
190 {
191 if ((remove(path) < 0) && (errno != ENOENT))
192 syslog(LOG_ERR, "smbns_krb: failed to remove ccache (%s)",
193 path);
194 }
195