keychain.c revision 4bff34e37def8a90f9194d81bc345c52ba20086a
/*
* 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 <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <libintl.h>
#include <netsmb/smb_dev.h>
#include <netsmb/smb_lib.h>
#include <netsmb/smb_keychain.h>
#include <cflib.h>
/* 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);
}