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]
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>
45 #include <netsmb/smb_dev.h>
46 #include <netsmb/smb_lib.h>
47 #include <netsmb/smb_keychain.h>
53 /* common func. for add/del/chk */
66 memset(&pk
, 0, sizeof (pk
));
75 * Add password hashes to the keychain.
77 if (lmhash
== NULL
|| nthash
== NULL
) {
78 err
= SMB_KEYCHAIN_BADPASSWD
;
81 memcpy(pk
.pk_lmhash
, lmhash
, SMBIOC_HASH_SZ
);
82 memcpy(pk
.pk_nthash
, nthash
, SMBIOC_HASH_SZ
);
88 * Copy domain and user.
91 err
= SMB_KEYCHAIN_BADDOMAIN
;
94 sz
= sizeof (pk
.pk_dom
);
95 if (strlcpy(pk
.pk_dom
, dom
, sz
) >= sz
) {
96 err
= SMB_KEYCHAIN_BADDOMAIN
;
100 err
= SMB_KEYCHAIN_BADUSER
;
103 sz
= sizeof (pk
.pk_usr
);
104 if (strlcpy(pk
.pk_usr
, usr
, sz
) >= sz
) {
105 err
= SMB_KEYCHAIN_BADUSER
;
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.
120 err
= SMB_KEYCHAIN_UNKNOWN
;
124 fd
= smb_open_driver();
126 err
= SMB_KEYCHAIN_NODRIVER
;
131 if (ioctl(fd
, cmd
, &pk
) < 0) {
136 if (cmd
== SMBIOC_PK_CHK
) {
138 memcpy(lmhash
, pk
.pk_lmhash
, SMBIOC_HASH_SZ
);
140 memcpy(nthash
, pk
.pk_nthash
, SMBIOC_HASH_SZ
);
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
,
161 uchar_t lmhash
[SMBIOC_HASH_SZ
];
162 uchar_t nthash
[SMBIOC_HASH_SZ
];
163 int err
, cmd
= SMBIOC_PK_ADD
;
166 return (SMB_KEYCHAIN_BADPASSWD
);
168 if ((err
= ntlm_compute_lm_hash(lmhash
, pass
)) != 0)
170 if ((err
= ntlm_compute_nt_hash(nthash
, pass
)) != 0)
173 err
= smbfs_keychain_cmn(cmd
, uid
, dom
, usr
, lmhash
, nthash
);
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
);
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
);
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
)
252 if (ctx
->ct_fullserver
== NULL
) {
253 DPRINT("ct_fullserver == NULL");
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
);
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
);
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
);
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
);
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
)
302 err
= smb_ctx_alloc(&ctx
);
307 err
= smb_ctx_setfullserver(ctx
, server
);
314 ctx
->ct_home
= strdup(home
);
317 err
= smb_ctx_readrc(ctx
);
322 strlcpy(dom
, ctx
->ct_domain
, maxdom
);
325 strlcpy(usr
, ctx
->ct_user
, maxusr
);