xref: /illumos-gate/usr/src/lib/libsmbfs/smb/keychain.c (revision 6e375c8351497b82ffa4f33cbf61d712999b4605)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * External interface to the libsmbfs/netsmb keychain
31  * storage mechanism.  This interface is consumed by
32  * the "smbutil" commands: login, logout, ...
33  * and by the SMBFS PAM module.
34  */
35 
36 #include <sys/types.h>
37 
38 #include <errno.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include <unistd.h>
42 #include <libintl.h>
43 
44 #include <netsmb/smb_dev.h>
45 #include <netsmb/smb_lib.h>
46 #include <netsmb/smb_keychain.h>
47 
48 #include <cflib.h>
49 
50 /* common func. for add/del/chk */
51 static int
52 smbfs_keychain_cmn(
53 	int cmd,
54 	uid_t uid,
55 	const char *dom,
56 	const char *usr,
57 	const char *pass)
58 {
59 	smbioc_pk_t pk;
60 	int err, fd;
61 
62 	memset(&pk, 0, sizeof (pk));
63 
64 	pk.pk_uid = uid;
65 
66 	switch (cmd) {
67 
68 	case SMBIOC_PK_ADD:
69 		if (pass == NULL)
70 			return (SMB_KEYCHAIN_BADPASSWD);
71 		if (strlcpy(pk.pk_pass, pass, sizeof (pk.pk_pass)) >=
72 		    sizeof (pk.pk_pass))
73 			return (SMB_KEYCHAIN_BADPASSWD);
74 		/* FALLTHROUGH */
75 
76 	case SMBIOC_PK_CHK:
77 	case SMBIOC_PK_DEL:
78 		if (dom == NULL)
79 			return (SMB_KEYCHAIN_BADDOMAIN);
80 		if (strlcpy(pk.pk_dom, dom, sizeof (pk.pk_dom)) >=
81 		    sizeof (pk.pk_dom))
82 			return (SMB_KEYCHAIN_BADDOMAIN);
83 		if (usr == NULL)
84 			return (SMB_KEYCHAIN_BADUSER);
85 		if (strlcpy(pk.pk_usr, usr, sizeof (pk.pk_usr)) >=
86 		    sizeof (pk.pk_usr))
87 			return (SMB_KEYCHAIN_BADUSER);
88 		break;
89 
90 	case SMBIOC_PK_DEL_OWNER:	/* all owned by the caller */
91 	case SMBIOC_PK_DEL_EVERYONE:	/* all owned by everyone */
92 		/*
93 		 * These two do not copyin any args, but we'll
94 		 * pass &pk here anyway just so we can use the
95 		 * common code path below.
96 		 */
97 		break;
98 
99 	default:
100 		return (SMB_KEYCHAIN_UNKNOWN);
101 	}
102 
103 	fd = smb_open_driver();
104 	if (fd < 0) {
105 		err = SMB_KEYCHAIN_NODRIVER;
106 		goto out;
107 	}
108 
109 	err = 0;
110 	if (ioctl(fd, cmd, &pk) < 0)
111 		err = errno;
112 
113 	close(fd);
114 out:
115 	memset(&pk, 0, sizeof (pk));
116 	return (err);
117 }
118 
119 /* Add a password to the keychain. */
120 int
121 smbfs_keychain_add(uid_t uid, const char *dom, const char *usr,
122 	const char *pass)
123 {
124 	return (smbfs_keychain_cmn(SMBIOC_PK_ADD, uid, dom, usr, pass));
125 }
126 
127 /* Delete a password from the keychain. */
128 int
129 smbfs_keychain_del(uid_t uid, const char *dom, const char *usr)
130 {
131 	return (smbfs_keychain_cmn(SMBIOC_PK_DEL, uid, dom, usr, NULL));
132 }
133 
134 /*
135  * Check for existence of a keychain entry.
136  * Returns 0 if it exists, else ENOENT.
137  */
138 int
139 smbfs_keychain_chk(const char *dom, const char *usr)
140 {
141 	return (smbfs_keychain_cmn(SMBIOC_PK_CHK, (uid_t)-1, dom, usr, NULL));
142 }
143 
144 /*
145  * Delete all keychain entries owned by the caller.
146  */
147 int
148 smbfs_keychain_del_owner()
149 {
150 	return (smbfs_keychain_cmn(SMBIOC_PK_DEL_OWNER, getuid(), 0, 0, 0));
151 }
152 
153 /*
154  * Delete all keychain entries (regardless of onwer).
155  * Requires super-user privliege.
156  */
157 int
158 smbfs_keychain_del_everyone()
159 {
160 	return (smbfs_keychain_cmn(SMBIOC_PK_DEL_EVERYONE, getuid(), 0, 0, 0));
161 }
162 
163 
164 /*
165  * This is not really part of the keychain library,
166  * but is typically needed in code that wants to
167  * provide (editable) defaults for domain/user
168  *
169  * Get default domain and user names
170  * Server name is optional.
171  */
172 int
173 smbfs_default_dom_usr(const char *home, const char *server,
174 	char *dom, int maxdom, char *usr, int maxusr)
175 {
176 	struct smb_ctx sctx, *ctx = &sctx;
177 	int err;
178 
179 	err = smb_ctx_init(ctx, 0, NULL, SMBL_VC, SMBL_VC, SMB_ST_ANY);
180 	if (err)
181 		return (err);
182 	if (server)
183 		smb_ctx_setserver(ctx, server);
184 	if (home && *home)
185 		ctx->ct_home = (char *)home;
186 	err = smb_ctx_readrc(ctx);
187 	if (err)
188 		return (err);
189 	if (smb_rc)
190 		rc_close(smb_rc);
191 
192 	if (dom)
193 		strlcpy(dom, ctx->ct_ssn.ioc_workgroup, maxdom);
194 
195 	if (usr)
196 		strlcpy(usr, ctx->ct_ssn.ioc_user, maxusr);
197 
198 	return (0);
199 }
200