/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" /* * External interface to the libsmbfs/netsmb keychain * storage mechanism. This interface is consumed by * the "smbutil" commands: login, logout, ... * and by the SMBFS PAM module. */ #include #include #include #include #include #include #include #include #include #include /* common func. for add/del/chk */ static int smbfs_keychain_cmn( int cmd, uid_t uid, const char *dom, const char *usr, const char *pass) { smbioc_pk_t pk; int err, fd; memset(&pk, 0, sizeof (pk)); pk.pk_uid = uid; switch (cmd) { case SMBIOC_PK_ADD: if (pass == NULL) return (SMB_KEYCHAIN_BADPASSWD); if (strlcpy(pk.pk_pass, pass, sizeof (pk.pk_pass)) >= sizeof (pk.pk_pass)) return (SMB_KEYCHAIN_BADPASSWD); /* FALLTHROUGH */ case SMBIOC_PK_CHK: case SMBIOC_PK_DEL: if (dom == NULL) return (SMB_KEYCHAIN_BADDOMAIN); if (strlcpy(pk.pk_dom, dom, sizeof (pk.pk_dom)) >= sizeof (pk.pk_dom)) return (SMB_KEYCHAIN_BADDOMAIN); if (usr == NULL) return (SMB_KEYCHAIN_BADUSER); if (strlcpy(pk.pk_usr, usr, sizeof (pk.pk_usr)) >= sizeof (pk.pk_usr)) return (SMB_KEYCHAIN_BADUSER); break; case SMBIOC_PK_DEL_OWNER: /* all owned by the caller */ case SMBIOC_PK_DEL_EVERYONE: /* all owned by everyone */ /* * These two do not copyin any args, but we'll * pass &pk here anyway just so we can use the * common code path below. */ break; default: return (SMB_KEYCHAIN_UNKNOWN); } fd = smb_open_driver(); if (fd < 0) { err = SMB_KEYCHAIN_NODRIVER; goto out; } err = 0; if (ioctl(fd, cmd, &pk) < 0) err = errno; close(fd); out: memset(&pk, 0, sizeof (pk)); return (err); } /* Add a password to the keychain. */ int smbfs_keychain_add(uid_t uid, const char *dom, const char *usr, const char *pass) { return (smbfs_keychain_cmn(SMBIOC_PK_ADD, uid, dom, usr, pass)); } /* Delete a password from the keychain. */ int smbfs_keychain_del(uid_t uid, const char *dom, const char *usr) { return (smbfs_keychain_cmn(SMBIOC_PK_DEL, uid, dom, usr, NULL)); } /* * Check for existence of a keychain entry. * Returns 0 if it exists, else ENOENT. */ int smbfs_keychain_chk(const char *dom, const char *usr) { return (smbfs_keychain_cmn(SMBIOC_PK_CHK, (uid_t)-1, dom, usr, NULL)); } /* * Delete all keychain entries owned by the caller. */ int smbfs_keychain_del_owner() { return (smbfs_keychain_cmn(SMBIOC_PK_DEL_OWNER, getuid(), 0, 0, 0)); } /* * Delete all keychain entries (regardless of onwer). * Requires super-user privliege. */ int smbfs_keychain_del_everyone() { return (smbfs_keychain_cmn(SMBIOC_PK_DEL_EVERYONE, getuid(), 0, 0, 0)); } /* * This is not really part of the keychain library, * but is typically needed in code that wants to * provide (editable) defaults for domain/user * * Get default domain and user names * Server name is optional. */ int smbfs_default_dom_usr(const char *home, const char *server, char *dom, int maxdom, char *usr, int maxusr) { struct smb_ctx sctx, *ctx = &sctx; int err; err = smb_ctx_init(ctx, 0, NULL, SMBL_VC, SMBL_VC, SMB_ST_ANY); if (err) return (err); if (server) smb_ctx_setserver(ctx, server); if (home && *home) ctx->ct_home = (char *)home; err = smb_ctx_readrc(ctx); if (err) return (err); if (smb_rc) rc_close(smb_rc); if (dom) strlcpy(dom, ctx->ct_ssn.ioc_workgroup, maxdom); if (usr) strlcpy(usr, ctx->ct_ssn.ioc_user, maxusr); return (0); }