dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libsmbfs / smb / keychain.c
blob0fb2262201b832bee517a72c6d8e9a73f068d805
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
29 * External interface to the libsmbfs/netsmb keychain
30 * storage mechanism. This interface is consumed by
31 * the "smbutil" commands: login, logout, ...
32 * and by the SMBFS PAM module.
35 #include <sys/types.h>
37 #include <errno.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
42 #include <libintl.h>
44 #include <cflib.h>
45 #include <netsmb/smb_dev.h>
46 #include <netsmb/smb_lib.h>
47 #include <netsmb/smb_keychain.h>
49 #include "charsets.h"
50 #include "private.h"
51 #include "ntlm.h"
53 /* common func. for add/del/chk */
54 static int
55 smbfs_keychain_cmn(
56 int cmd,
57 uid_t uid,
58 const char *dom,
59 const char *usr,
60 uchar_t *lmhash,
61 uchar_t *nthash)
63 smbioc_pk_t pk;
64 int err, fd, sz;
66 memset(&pk, 0, sizeof (pk));
67 pk.pk_uid = uid;
68 err = 0;
69 fd = -1;
71 switch (cmd) {
73 case SMBIOC_PK_ADD:
75 * Add password hashes to the keychain.
77 if (lmhash == NULL || nthash == NULL) {
78 err = SMB_KEYCHAIN_BADPASSWD;
79 goto out;
81 memcpy(pk.pk_lmhash, lmhash, SMBIOC_HASH_SZ);
82 memcpy(pk.pk_nthash, nthash, SMBIOC_HASH_SZ);
83 /* FALLTHROUGH */
85 case SMBIOC_PK_CHK:
86 case SMBIOC_PK_DEL:
88 * Copy domain and user.
90 if (dom == NULL) {
91 err = SMB_KEYCHAIN_BADDOMAIN;
92 goto out;
94 sz = sizeof (pk.pk_dom);
95 if (strlcpy(pk.pk_dom, dom, sz) >= sz) {
96 err = SMB_KEYCHAIN_BADDOMAIN;
97 goto out;
99 if (usr == NULL) {
100 err = SMB_KEYCHAIN_BADUSER;
101 goto out;
103 sz = sizeof (pk.pk_usr);
104 if (strlcpy(pk.pk_usr, usr, sz) >= sz) {
105 err = SMB_KEYCHAIN_BADUSER;
106 goto out;
108 break;
110 case SMBIOC_PK_DEL_OWNER: /* all owned by the caller */
111 case SMBIOC_PK_DEL_EVERYONE: /* all owned by everyone */
113 * These two do not copyin any args, but we'll
114 * pass pk here anyway just so we can use the
115 * common code path below.
117 break;
119 default:
120 err = SMB_KEYCHAIN_UNKNOWN;
121 goto out;
124 fd = smb_open_driver();
125 if (fd < 0) {
126 err = SMB_KEYCHAIN_NODRIVER;
127 goto out;
130 err = 0;
131 if (ioctl(fd, cmd, &pk) < 0) {
132 err = errno;
133 goto out;
136 if (cmd == SMBIOC_PK_CHK) {
137 if (lmhash != NULL)
138 memcpy(lmhash, pk.pk_lmhash, SMBIOC_HASH_SZ);
139 if (nthash != NULL)
140 memcpy(nthash, pk.pk_nthash, SMBIOC_HASH_SZ);
143 out:
144 if (fd != -1)
145 close(fd);
147 return (err);
151 * Add a password to the keychain.
153 * Note: pass is a cleartext password.
154 * We use it here to compute the LM hash and NT hash,
155 * and then store ONLY the hashes.
158 smbfs_keychain_add(uid_t uid, const char *dom, const char *usr,
159 const char *pass)
161 uchar_t lmhash[SMBIOC_HASH_SZ];
162 uchar_t nthash[SMBIOC_HASH_SZ];
163 int err, cmd = SMBIOC_PK_ADD;
165 if (pass == NULL)
166 return (SMB_KEYCHAIN_BADPASSWD);
168 if ((err = ntlm_compute_lm_hash(lmhash, pass)) != 0)
169 return (err);
170 if ((err = ntlm_compute_nt_hash(nthash, pass)) != 0)
171 return (err);
173 err = smbfs_keychain_cmn(cmd, uid, dom, usr, lmhash, nthash);
174 return (err);
177 /* Variant of the above that takes an NT hash. */
179 smbfs_keychain_addhash(uid_t uid, const char *dom, const char *usr,
180 const uchar_t *nthash)
182 static const uchar_t lmhash[SMBIOC_HASH_SZ] = { 0 };
183 int err, cmd = SMBIOC_PK_ADD;
184 err = smbfs_keychain_cmn(cmd, uid, dom, usr,
185 (uchar_t *)lmhash, (uchar_t *)nthash);
186 return (err);
189 /* Delete a password from the keychain. */
191 smbfs_keychain_del(uid_t uid, const char *dom, const char *usr)
193 return (smbfs_keychain_cmn(SMBIOC_PK_DEL, uid, dom, usr, NULL, NULL));
197 * Check for existence of a keychain entry.
198 * Returns 0 if it exists, else ENOENT.
201 smbfs_keychain_chk(const char *dom, const char *usr)
203 uid_t uid = (uid_t)-1;
204 return (smbfs_keychain_cmn(SMBIOC_PK_CHK, uid, dom, usr, NULL, NULL));
208 * Get the stored hashes
211 smbfs_keychain_get(const char *dom, const char *usr,
212 uchar_t *lmhash, uchar_t *nthash)
214 uid_t uid = (uid_t)-1;
215 int err, cmd = SMBIOC_PK_CHK;
217 err = smbfs_keychain_cmn(cmd, uid, dom, usr, lmhash, nthash);
218 return (err);
222 * Delete all keychain entries owned by the caller.
225 smbfs_keychain_del_owner()
227 int cmd = SMBIOC_PK_DEL_OWNER;
228 uid_t uid = getuid();
229 return (smbfs_keychain_cmn(cmd, uid, NULL, NULL, NULL, NULL));
233 * Delete all keychain entries (regardless of onwer).
234 * Requires super-user privliege.
237 smbfs_keychain_del_everyone()
239 int cmd = SMBIOC_PK_DEL_EVERYONE;
240 uid_t uid = getuid();
241 return (smbfs_keychain_cmn(cmd, uid, NULL, NULL, NULL, NULL));
245 * Private function to get keychain p/w hashes.
248 smb_get_keychain(struct smb_ctx *ctx)
250 int err;
252 if (ctx->ct_fullserver == NULL) {
253 DPRINT("ct_fullserver == NULL");
254 return (EINVAL);
258 * 1st: try lookup using system name
260 err = smbfs_keychain_get(ctx->ct_fullserver, ctx->ct_user,
261 ctx->ct_lmhash, ctx->ct_nthash);
262 if (!err) {
263 ctx->ct_flags |= SMBCF_KCFOUND;
264 DPRINT("found keychain entry for"
265 " server/user: %s/%s\n",
266 ctx->ct_fullserver, ctx->ct_user);
267 return (0);
271 * 2nd: try lookup using domain name
273 err = smbfs_keychain_get(ctx->ct_domain, ctx->ct_user,
274 ctx->ct_lmhash, ctx->ct_nthash);
275 if (!err) {
276 ctx->ct_flags |= (SMBCF_KCFOUND | SMBCF_KCDOMAIN);
277 DPRINT("found keychain entry for"
278 " domain/user: %s/%s\n",
279 ctx->ct_domain, ctx->ct_user);
280 return (0);
283 return (err);
288 * This is not really part of the keychain library,
289 * but is typically needed in code that wants to
290 * provide (editable) defaults for domain/user
292 * Get default domain and user names
293 * Server name is optional.
296 smbfs_default_dom_usr(const char *home, const char *server,
297 char *dom, int maxdom, char *usr, int maxusr)
299 struct smb_ctx *ctx;
300 int err;
302 err = smb_ctx_alloc(&ctx);
303 if (err)
304 return (err);
306 if (server) {
307 err = smb_ctx_setfullserver(ctx, server);
308 if (err != 0)
309 goto out;
312 if (home && *home) {
313 free(ctx->ct_home);
314 ctx->ct_home = strdup(home);
317 err = smb_ctx_readrc(ctx);
318 if (err)
319 goto out;
321 if (dom)
322 strlcpy(dom, ctx->ct_domain, maxdom);
324 if (usr)
325 strlcpy(usr, ctx->ct_user, maxusr);
327 out:
328 smb_ctx_free(ctx);
329 return (err);