8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / pam_modules / krb5 / utils.c
blob970ba6614a3f26b715956c5651180f8f18de2224
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <security/pam_appl.h>
27 #include <pwd.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <malloc.h>
31 #include <unistd.h>
32 #include <ctype.h>
33 #include <syslog.h>
34 #include <errno.h>
36 #include "utils.h"
38 extern const char *error_message(long);
40 /* ******************************************************************** */
41 /* */
42 /* Utilities Functions */
43 /* */
44 /* ******************************************************************** */
47 * get_pw_uid():
48 * To get the uid from the passwd entry for specified user
49 * It returns 0 if the user can't be found, otherwise returns 1.
51 int
52 get_pw_uid(char *user, uid_t *uid)
54 struct passwd sp;
55 char buffer[1024];
57 if (getpwnam_r(user, &sp, buffer, sizeof (buffer)) == NULL) {
58 return (0);
61 *uid = sp.pw_uid;
63 return (1);
67 * get_pw_gid():
68 * To get the gid from the passwd entry for specified user
69 * It returns 0 if the user can't be found, otherwise returns 1.
71 int
72 get_pw_gid(char *user, gid_t *gid)
74 struct passwd sp;
75 char buffer[1024];
77 if (getpwnam_r(user, &sp, buffer, sizeof (buffer)) == NULL) {
78 return (0);
81 *gid = sp.pw_gid;
83 return (1);
88 * get_kmd_kuser():
89 * To get the kerberos user name for the specified user.
90 * Assumes that the kuser string is allocated. It will be
91 * overwritten. This saves us having to deal will allocating
92 * and freeing the kuser string.
94 * RFC 1510 does not mention how to handle mixed case domainnames
95 * while constructing client principals. So we will follow the same
96 * procedure as for server principals and lowercase the domainname.
98 * Returns:
99 * PAM_BUF_ERR - if there is an error from krb5_sname_to_principal(),
100 * or krb5_unparse_name()
101 * 0 - if there was no error
104 get_kmd_kuser(krb5_context kcontext, const char *user, char *kuser, int length)
106 if (strcmp(user, ROOT_UNAME) == 0) {
107 krb5_principal princ;
108 char *name, *princname, *lasts;
110 if (krb5_sname_to_principal(kcontext, NULL, ROOT_UNAME,
111 KRB5_NT_SRV_HST, &princ)) {
112 return (PAM_BUF_ERR);
114 if (krb5_unparse_name(kcontext, princ, &princname)) {
115 krb5_free_principal(kcontext, princ);
116 return (PAM_BUF_ERR);
118 /* just interested in princ name before the @REALM part */
119 if ((name = strtok_r(princname, "@", &lasts)) == NULL) {
120 krb5_free_principal(kcontext, princ);
121 free(princname);
122 return (PAM_BUF_ERR);
124 if (strlcpy(kuser, name, length) >= length) {
125 krb5_free_principal(kcontext, princ);
126 free(princname);
127 return (PAM_BUF_ERR);
129 krb5_free_principal(kcontext, princ);
130 free(princname);
131 } else {
132 if (strlcpy(kuser, user, length) >= length) {
133 return (PAM_BUF_ERR);
136 return (0);
140 * return true (1) if the user's key is in the (default) keytab
143 key_in_keytab(const char *user, int debug)
145 krb5_keytab kt_handle;
146 krb5_keytab_entry kt_ent;
147 char *whoami = "key_in_keytab";
148 krb5_error_code retval = 0;
149 krb5_error_code code = 0;
150 krb5_context kcontext = NULL;
151 krb5_principal princ = NULL;
152 char kuser[2*MAXHOSTNAMELEN];
155 if (debug)
156 __pam_log(LOG_AUTH | LOG_DEBUG,
157 "PAM-KRB5 (%s): start for user '%s'",
158 whoami, user ? user : "<null>");
160 if (!user)
161 return (retval);
163 /* need to free context with krb5_free_context */
164 if (code = krb5_init_secure_context(&kcontext)) {
165 if (debug)
166 __pam_log(LOG_AUTH | LOG_DEBUG,
167 "PAM-KRB5 (%s): Error initializing "
168 "krb5: %s", whoami,
169 error_message(code));
170 return (retval);
173 if ((code = get_kmd_kuser(kcontext, (const char *)user, kuser,
174 2*MAXHOSTNAMELEN)) != 0) {
175 goto out;
178 /* need to free princ with krb5_free_principal */
179 if ((code = krb5_parse_name(kcontext, kuser, &princ)) != 0) {
180 if (debug)
181 __pam_log(LOG_AUTH | LOG_DEBUG,
182 "PAM-KRB5 (%s): can't parse name (%s)",
183 whoami, error_message(code));
184 goto out;
187 /* need to close keytab handle with krb5_kt_close */
188 if ((code = krb5_kt_default(kcontext, &kt_handle))) {
189 if (debug)
190 __pam_log(LOG_AUTH | LOG_DEBUG,
191 "PAM-KRB5 (%s): krb5_kt_default failed (%s)",
192 whoami, error_message(code));
193 goto out;
196 code = krb5_kt_get_entry(kcontext, kt_handle, princ, 0, 0, &kt_ent);
197 if (code != 0) {
198 if (code == ENOENT) {
199 if (debug)
200 __pam_log(LOG_AUTH | LOG_DEBUG,
201 "PAM-KRB5 (%s): "
202 "Keytab does not exist",
203 whoami);
204 } else if (code == KRB5_KT_NOTFOUND) {
205 if (debug)
206 __pam_log(LOG_AUTH | LOG_DEBUG,
207 "PAM-KRB5 (%s): "
208 "No entry for principal "
209 "'%s' exists in keytab",
210 whoami, kuser);
211 } else {
212 if (debug)
213 __pam_log(LOG_AUTH | LOG_DEBUG,
214 "PAM-KRB5 (%s): "
215 "krb5_kt_get_entry failed (%s)",
216 whoami, error_message(code));
218 } else { /* Key found in keytab, return success */
219 (void) krb5_kt_free_entry(kcontext, &kt_ent);
220 if (debug)
221 __pam_log(LOG_AUTH | LOG_DEBUG,
222 "PAM-KRB5 (%s): "
223 "keytab entry for '%s' found",
224 whoami, user);
225 retval = 1;
228 (void) krb5_kt_close(kcontext, kt_handle);
229 out:
230 if (princ && kcontext)
231 krb5_free_principal(kcontext, princ);
233 if (kcontext)
234 krb5_free_context(kcontext);
236 return (retval);