14bff34e3Sthurlow /* 24bff34e3Sthurlow * CDDL HEADER START 34bff34e3Sthurlow * 44bff34e3Sthurlow * The contents of this file are subject to the terms of the 54bff34e3Sthurlow * Common Development and Distribution License (the "License"). 64bff34e3Sthurlow * You may not use this file except in compliance with the License. 74bff34e3Sthurlow * 84bff34e3Sthurlow * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 94bff34e3Sthurlow * or http://www.opensolaris.org/os/licensing. 104bff34e3Sthurlow * See the License for the specific language governing permissions 114bff34e3Sthurlow * and limitations under the License. 124bff34e3Sthurlow * 134bff34e3Sthurlow * When distributing Covered Code, include this CDDL HEADER in each 144bff34e3Sthurlow * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 154bff34e3Sthurlow * If applicable, add the following below this CDDL HEADER, with the 164bff34e3Sthurlow * fields enclosed by brackets "[]" replaced with your own identifying 174bff34e3Sthurlow * information: Portions Copyright [yyyy] [name of copyright owner] 184bff34e3Sthurlow * 194bff34e3Sthurlow * CDDL HEADER END 204bff34e3Sthurlow */ 214bff34e3Sthurlow 224bff34e3Sthurlow /* 23*613a2f6bSGordon Ross * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 244bff34e3Sthurlow * Use is subject to license terms. 254bff34e3Sthurlow */ 264bff34e3Sthurlow 274bff34e3Sthurlow /* 284bff34e3Sthurlow * External interface to the libsmbfs/netsmb keychain 294bff34e3Sthurlow * storage mechanism. This interface is consumed by 304bff34e3Sthurlow * the "smbutil" commands: login, logout, ... 314bff34e3Sthurlow * and by the SMBFS PAM module. 324bff34e3Sthurlow */ 334bff34e3Sthurlow 344bff34e3Sthurlow #include <sys/types.h> 354bff34e3Sthurlow 364bff34e3Sthurlow #include <errno.h> 374bff34e3Sthurlow #include <stdio.h> 38*613a2f6bSGordon Ross #include <stdlib.h> 394bff34e3Sthurlow #include <string.h> 404bff34e3Sthurlow #include <unistd.h> 414bff34e3Sthurlow #include <libintl.h> 424bff34e3Sthurlow 43*613a2f6bSGordon Ross #include <cflib.h> 444bff34e3Sthurlow #include <netsmb/smb_dev.h> 454bff34e3Sthurlow #include <netsmb/smb_lib.h> 464bff34e3Sthurlow #include <netsmb/smb_keychain.h> 474bff34e3Sthurlow 48*613a2f6bSGordon Ross #include "charsets.h" 49*613a2f6bSGordon Ross #include "private.h" 50*613a2f6bSGordon Ross #include "ntlm.h" 514bff34e3Sthurlow 524bff34e3Sthurlow /* common func. for add/del/chk */ 534bff34e3Sthurlow static int 544bff34e3Sthurlow smbfs_keychain_cmn( 554bff34e3Sthurlow int cmd, 564bff34e3Sthurlow uid_t uid, 574bff34e3Sthurlow const char *dom, 584bff34e3Sthurlow const char *usr, 59*613a2f6bSGordon Ross uchar_t *lmhash, 60*613a2f6bSGordon Ross uchar_t *nthash) 614bff34e3Sthurlow { 624bff34e3Sthurlow smbioc_pk_t pk; 63*613a2f6bSGordon Ross int err, fd, sz; 644bff34e3Sthurlow 654bff34e3Sthurlow memset(&pk, 0, sizeof (pk)); 664bff34e3Sthurlow pk.pk_uid = uid; 67*613a2f6bSGordon Ross err = 0; 68*613a2f6bSGordon Ross fd = -1; 694bff34e3Sthurlow 704bff34e3Sthurlow switch (cmd) { 714bff34e3Sthurlow 724bff34e3Sthurlow case SMBIOC_PK_ADD: 73*613a2f6bSGordon Ross /* 74*613a2f6bSGordon Ross * Add password hashes to the keychain. 75*613a2f6bSGordon Ross */ 76*613a2f6bSGordon Ross if (lmhash == NULL || nthash == NULL) { 77*613a2f6bSGordon Ross err = SMB_KEYCHAIN_BADPASSWD; 78*613a2f6bSGordon Ross goto out; 79*613a2f6bSGordon Ross } 80*613a2f6bSGordon Ross memcpy(pk.pk_lmhash, lmhash, SMBIOC_HASH_SZ); 81*613a2f6bSGordon Ross memcpy(pk.pk_nthash, nthash, SMBIOC_HASH_SZ); 824bff34e3Sthurlow /* FALLTHROUGH */ 834bff34e3Sthurlow 844bff34e3Sthurlow case SMBIOC_PK_CHK: 854bff34e3Sthurlow case SMBIOC_PK_DEL: 86*613a2f6bSGordon Ross /* 87*613a2f6bSGordon Ross * Copy domain and user. 88*613a2f6bSGordon Ross */ 89*613a2f6bSGordon Ross if (dom == NULL) { 90*613a2f6bSGordon Ross err = SMB_KEYCHAIN_BADDOMAIN; 91*613a2f6bSGordon Ross goto out; 92*613a2f6bSGordon Ross } 93*613a2f6bSGordon Ross sz = sizeof (pk.pk_dom); 94*613a2f6bSGordon Ross if (strlcpy(pk.pk_dom, dom, sz) >= sz) { 95*613a2f6bSGordon Ross err = SMB_KEYCHAIN_BADDOMAIN; 96*613a2f6bSGordon Ross goto out; 97*613a2f6bSGordon Ross } 98*613a2f6bSGordon Ross if (usr == NULL) { 99*613a2f6bSGordon Ross err = SMB_KEYCHAIN_BADUSER; 100*613a2f6bSGordon Ross goto out; 101*613a2f6bSGordon Ross } 102*613a2f6bSGordon Ross sz = sizeof (pk.pk_usr); 103*613a2f6bSGordon Ross if (strlcpy(pk.pk_usr, usr, sz) >= sz) { 104*613a2f6bSGordon Ross err = SMB_KEYCHAIN_BADUSER; 105*613a2f6bSGordon Ross goto out; 106*613a2f6bSGordon Ross } 1074bff34e3Sthurlow break; 1084bff34e3Sthurlow 1094bff34e3Sthurlow case SMBIOC_PK_DEL_OWNER: /* all owned by the caller */ 1104bff34e3Sthurlow case SMBIOC_PK_DEL_EVERYONE: /* all owned by everyone */ 1114bff34e3Sthurlow /* 1124bff34e3Sthurlow * These two do not copyin any args, but we'll 113*613a2f6bSGordon Ross * pass pk here anyway just so we can use the 1144bff34e3Sthurlow * common code path below. 1154bff34e3Sthurlow */ 1164bff34e3Sthurlow break; 1174bff34e3Sthurlow 1184bff34e3Sthurlow default: 119*613a2f6bSGordon Ross err = SMB_KEYCHAIN_UNKNOWN; 120*613a2f6bSGordon Ross goto out; 1214bff34e3Sthurlow } 1224bff34e3Sthurlow 1234bff34e3Sthurlow fd = smb_open_driver(); 1244bff34e3Sthurlow if (fd < 0) { 1254bff34e3Sthurlow err = SMB_KEYCHAIN_NODRIVER; 1264bff34e3Sthurlow goto out; 1274bff34e3Sthurlow } 1284bff34e3Sthurlow 1294bff34e3Sthurlow err = 0; 130*613a2f6bSGordon Ross if (ioctl(fd, cmd, &pk) < 0) { 1314bff34e3Sthurlow err = errno; 132*613a2f6bSGordon Ross goto out; 133*613a2f6bSGordon Ross } 1344bff34e3Sthurlow 135*613a2f6bSGordon Ross if (cmd == SMBIOC_PK_CHK) { 136*613a2f6bSGordon Ross if (lmhash != NULL) 137*613a2f6bSGordon Ross memcpy(lmhash, pk.pk_lmhash, SMBIOC_HASH_SZ); 138*613a2f6bSGordon Ross if (nthash != NULL) 139*613a2f6bSGordon Ross memcpy(nthash, pk.pk_nthash, SMBIOC_HASH_SZ); 140*613a2f6bSGordon Ross } 141*613a2f6bSGordon Ross 1424bff34e3Sthurlow out: 143*613a2f6bSGordon Ross if (fd != -1) 144*613a2f6bSGordon Ross close(fd); 145*613a2f6bSGordon Ross 1464bff34e3Sthurlow return (err); 1474bff34e3Sthurlow } 1484bff34e3Sthurlow 149*613a2f6bSGordon Ross /* 150*613a2f6bSGordon Ross * Add a password to the keychain. 151*613a2f6bSGordon Ross * 152*613a2f6bSGordon Ross * Note: pass is a cleartext password. 153*613a2f6bSGordon Ross * We use it here to compute the LM hash and NT hash, 154*613a2f6bSGordon Ross * and then store ONLY the hashes. 155*613a2f6bSGordon Ross */ 1564bff34e3Sthurlow int 1574bff34e3Sthurlow smbfs_keychain_add(uid_t uid, const char *dom, const char *usr, 1584bff34e3Sthurlow const char *pass) 1594bff34e3Sthurlow { 160*613a2f6bSGordon Ross uchar_t lmhash[SMBIOC_HASH_SZ]; 161*613a2f6bSGordon Ross uchar_t nthash[SMBIOC_HASH_SZ]; 162*613a2f6bSGordon Ross int err, cmd = SMBIOC_PK_ADD; 163*613a2f6bSGordon Ross 164*613a2f6bSGordon Ross if (pass == NULL) 165*613a2f6bSGordon Ross return (SMB_KEYCHAIN_BADPASSWD); 166*613a2f6bSGordon Ross 167*613a2f6bSGordon Ross if ((err = ntlm_compute_lm_hash(lmhash, pass)) != 0) 168*613a2f6bSGordon Ross return (err); 169*613a2f6bSGordon Ross if ((err = ntlm_compute_nt_hash(nthash, pass)) != 0) 170*613a2f6bSGordon Ross return (err); 171*613a2f6bSGordon Ross 172*613a2f6bSGordon Ross err = smbfs_keychain_cmn(cmd, uid, dom, usr, lmhash, nthash); 173*613a2f6bSGordon Ross return (err); 1744bff34e3Sthurlow } 1754bff34e3Sthurlow 1764bff34e3Sthurlow /* Delete a password from the keychain. */ 1774bff34e3Sthurlow int 1784bff34e3Sthurlow smbfs_keychain_del(uid_t uid, const char *dom, const char *usr) 1794bff34e3Sthurlow { 180*613a2f6bSGordon Ross return (smbfs_keychain_cmn(SMBIOC_PK_DEL, uid, dom, usr, NULL, NULL)); 1814bff34e3Sthurlow } 1824bff34e3Sthurlow 1834bff34e3Sthurlow /* 1844bff34e3Sthurlow * Check for existence of a keychain entry. 1854bff34e3Sthurlow * Returns 0 if it exists, else ENOENT. 1864bff34e3Sthurlow */ 1874bff34e3Sthurlow int 1884bff34e3Sthurlow smbfs_keychain_chk(const char *dom, const char *usr) 1894bff34e3Sthurlow { 190*613a2f6bSGordon Ross uid_t uid = (uid_t)-1; 191*613a2f6bSGordon Ross return (smbfs_keychain_cmn(SMBIOC_PK_CHK, uid, dom, usr, NULL, NULL)); 192*613a2f6bSGordon Ross } 193*613a2f6bSGordon Ross 194*613a2f6bSGordon Ross /* 195*613a2f6bSGordon Ross * Get the stored hashes 196*613a2f6bSGordon Ross */ 197*613a2f6bSGordon Ross int 198*613a2f6bSGordon Ross smbfs_keychain_get(const char *dom, const char *usr, 199*613a2f6bSGordon Ross uchar_t *lmhash, uchar_t *nthash) 200*613a2f6bSGordon Ross { 201*613a2f6bSGordon Ross uid_t uid = (uid_t)-1; 202*613a2f6bSGordon Ross int err, cmd = SMBIOC_PK_CHK; 203*613a2f6bSGordon Ross 204*613a2f6bSGordon Ross err = smbfs_keychain_cmn(cmd, uid, dom, usr, lmhash, nthash); 205*613a2f6bSGordon Ross return (err); 2064bff34e3Sthurlow } 2074bff34e3Sthurlow 2084bff34e3Sthurlow /* 2094bff34e3Sthurlow * Delete all keychain entries owned by the caller. 2104bff34e3Sthurlow */ 2114bff34e3Sthurlow int 2124bff34e3Sthurlow smbfs_keychain_del_owner() 2134bff34e3Sthurlow { 214*613a2f6bSGordon Ross int cmd = SMBIOC_PK_DEL_OWNER; 215*613a2f6bSGordon Ross uid_t uid = getuid(); 216*613a2f6bSGordon Ross return (smbfs_keychain_cmn(cmd, uid, NULL, NULL, NULL, NULL)); 2174bff34e3Sthurlow } 2184bff34e3Sthurlow 2194bff34e3Sthurlow /* 2204bff34e3Sthurlow * Delete all keychain entries (regardless of onwer). 2214bff34e3Sthurlow * Requires super-user privliege. 2224bff34e3Sthurlow */ 2234bff34e3Sthurlow int 2244bff34e3Sthurlow smbfs_keychain_del_everyone() 2254bff34e3Sthurlow { 226*613a2f6bSGordon Ross int cmd = SMBIOC_PK_DEL_EVERYONE; 227*613a2f6bSGordon Ross uid_t uid = getuid(); 228*613a2f6bSGordon Ross return (smbfs_keychain_cmn(cmd, uid, NULL, NULL, NULL, NULL)); 229*613a2f6bSGordon Ross } 230*613a2f6bSGordon Ross 231*613a2f6bSGordon Ross /* 232*613a2f6bSGordon Ross * Private function to get keychain p/w hashes. 233*613a2f6bSGordon Ross */ 234*613a2f6bSGordon Ross int 235*613a2f6bSGordon Ross smb_get_keychain(struct smb_ctx *ctx) 236*613a2f6bSGordon Ross { 237*613a2f6bSGordon Ross int err; 238*613a2f6bSGordon Ross 239*613a2f6bSGordon Ross if (ctx->ct_fullserver == NULL) { 240*613a2f6bSGordon Ross DPRINT("ct_fullserver == NULL"); 241*613a2f6bSGordon Ross return (EINVAL); 242*613a2f6bSGordon Ross } 243*613a2f6bSGordon Ross 244*613a2f6bSGordon Ross /* 245*613a2f6bSGordon Ross * 1st: try lookup using system name 246*613a2f6bSGordon Ross */ 247*613a2f6bSGordon Ross err = smbfs_keychain_get(ctx->ct_fullserver, ctx->ct_user, 248*613a2f6bSGordon Ross ctx->ct_lmhash, ctx->ct_nthash); 249*613a2f6bSGordon Ross if (!err) { 250*613a2f6bSGordon Ross ctx->ct_flags |= SMBCF_KCFOUND; 251*613a2f6bSGordon Ross DPRINT("found keychain entry for" 252*613a2f6bSGordon Ross " server/user: %s/%s\n", 253*613a2f6bSGordon Ross ctx->ct_fullserver, ctx->ct_user); 254*613a2f6bSGordon Ross return (0); 255*613a2f6bSGordon Ross } 256*613a2f6bSGordon Ross 257*613a2f6bSGordon Ross /* 258*613a2f6bSGordon Ross * 2nd: try lookup using domain name 259*613a2f6bSGordon Ross */ 260*613a2f6bSGordon Ross err = smbfs_keychain_get(ctx->ct_domain, ctx->ct_user, 261*613a2f6bSGordon Ross ctx->ct_lmhash, ctx->ct_nthash); 262*613a2f6bSGordon Ross if (!err) { 263*613a2f6bSGordon Ross ctx->ct_flags |= (SMBCF_KCFOUND | SMBCF_KCDOMAIN); 264*613a2f6bSGordon Ross DPRINT("found keychain entry for" 265*613a2f6bSGordon Ross " domain/user: %s/%s\n", 266*613a2f6bSGordon Ross ctx->ct_domain, ctx->ct_user); 267*613a2f6bSGordon Ross return (0); 268*613a2f6bSGordon Ross } 269*613a2f6bSGordon Ross 270*613a2f6bSGordon Ross return (err); 2714bff34e3Sthurlow } 2724bff34e3Sthurlow 2734bff34e3Sthurlow 2744bff34e3Sthurlow /* 2754bff34e3Sthurlow * This is not really part of the keychain library, 2764bff34e3Sthurlow * but is typically needed in code that wants to 2774bff34e3Sthurlow * provide (editable) defaults for domain/user 2784bff34e3Sthurlow * 2794bff34e3Sthurlow * Get default domain and user names 2804bff34e3Sthurlow * Server name is optional. 2814bff34e3Sthurlow */ 2824bff34e3Sthurlow int 2834bff34e3Sthurlow smbfs_default_dom_usr(const char *home, const char *server, 2844bff34e3Sthurlow char *dom, int maxdom, char *usr, int maxusr) 2854bff34e3Sthurlow { 286*613a2f6bSGordon Ross struct smb_ctx *ctx; 2874bff34e3Sthurlow int err; 2884bff34e3Sthurlow 289*613a2f6bSGordon Ross err = smb_ctx_alloc(&ctx); 2904bff34e3Sthurlow if (err) 2914bff34e3Sthurlow return (err); 292*613a2f6bSGordon Ross 2934bff34e3Sthurlow if (server) 294*613a2f6bSGordon Ross smb_ctx_setfullserver(ctx, server); 295*613a2f6bSGordon Ross 296*613a2f6bSGordon Ross if (home && *home) { 297*613a2f6bSGordon Ross if (ctx->ct_home) 298*613a2f6bSGordon Ross free(ctx->ct_home); 299*613a2f6bSGordon Ross ctx->ct_home = strdup(home); 300*613a2f6bSGordon Ross } 301*613a2f6bSGordon Ross 3024bff34e3Sthurlow err = smb_ctx_readrc(ctx); 3034bff34e3Sthurlow if (err) 304*613a2f6bSGordon Ross goto out; 3054bff34e3Sthurlow 3064bff34e3Sthurlow if (dom) 307*613a2f6bSGordon Ross strlcpy(dom, ctx->ct_domain, maxdom); 3084bff34e3Sthurlow 3094bff34e3Sthurlow if (usr) 310*613a2f6bSGordon Ross strlcpy(usr, ctx->ct_user, maxusr); 3114bff34e3Sthurlow 312*613a2f6bSGordon Ross out: 313*613a2f6bSGordon Ross smb_ctx_free(ctx); 314*613a2f6bSGordon Ross return (err); 3154bff34e3Sthurlow } 316