| @@ -1,287 +1,287 @@ | | | @@ -1,287 +1,287 @@ |
1 | /* $NetBSD: pam_ksu.c,v 1.5 2011/04/25 22:01:04 christos Exp $ */ | | 1 | /* $NetBSD: pam_ksu.c,v 1.6 2011/04/25 22:03:20 christos Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2002 Jacques A. Vidrine <nectar@FreeBSD.org> | | 4 | * Copyright (c) 2002 Jacques A. Vidrine <nectar@FreeBSD.org> |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
15 | * | | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | | 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | | 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
26 | * SUCH DAMAGE. | | 26 | * SUCH DAMAGE. |
27 | */ | | 27 | */ |
28 | #include <sys/cdefs.h> | | 28 | #include <sys/cdefs.h> |
29 | #ifdef __FreeBSD__ | | 29 | #ifdef __FreeBSD__ |
30 | __FBSDID("$FreeBSD: src/lib/libpam/modules/pam_ksu/pam_ksu.c,v 1.5 2004/02/10 10:13:21 des Exp $"); | | 30 | __FBSDID("$FreeBSD: src/lib/libpam/modules/pam_ksu/pam_ksu.c,v 1.5 2004/02/10 10:13:21 des Exp $"); |
31 | #else | | 31 | #else |
32 | __RCSID("$NetBSD: pam_ksu.c,v 1.5 2011/04/25 22:01:04 christos Exp $"); | | 32 | __RCSID("$NetBSD: pam_ksu.c,v 1.6 2011/04/25 22:03:20 christos Exp $"); |
33 | #endif | | 33 | #endif |
34 | | | 34 | |
35 | #include <sys/param.h> | | 35 | #include <sys/param.h> |
36 | #include <errno.h> | | 36 | #include <errno.h> |
37 | #include <stdio.h> | | 37 | #include <stdio.h> |
38 | #include <stdlib.h> | | 38 | #include <stdlib.h> |
39 | #include <string.h> | | 39 | #include <string.h> |
40 | #include <unistd.h> | | 40 | #include <unistd.h> |
41 | | | 41 | |
42 | #include <krb5/krb5.h> | | 42 | #include <krb5/krb5.h> |
43 | | | 43 | |
44 | #define PAM_SM_AUTH | | 44 | #define PAM_SM_AUTH |
45 | #define PAM_SM_CRED | | 45 | #define PAM_SM_CRED |
46 | #include <security/pam_appl.h> | | 46 | #include <security/pam_appl.h> |
47 | #include <security/pam_modules.h> | | 47 | #include <security/pam_modules.h> |
48 | #include <security/pam_mod_misc.h> | | 48 | #include <security/pam_mod_misc.h> |
49 | | | 49 | |
50 | static const char superuser[] = "root"; | | 50 | static const char superuser[] = "root"; |
51 | | | 51 | |
52 | #define PASSWORD_PROMPT "%s's password:" | | 52 | #define PASSWORD_PROMPT "%s's password:" |
53 | | | 53 | |
54 | static void log_krb5(krb5_context, krb5_error_code, const char *, ...) | | 54 | static void log_krb5(krb5_context, krb5_error_code, const char *, ...) |
55 | __printflike(3, 4); | | 55 | __printflike(3, 4); |
56 | static long get_su_principal(krb5_context, const char *, const char *, | | 56 | static long get_su_principal(krb5_context, const char *, const char *, |
57 | char **, krb5_principal *); | | 57 | char **, krb5_principal *); |
58 | static int auth_krb5(pam_handle_t *, krb5_context, const char *, | | 58 | static int auth_krb5(pam_handle_t *, krb5_context, const char *, |
59 | krb5_principal); | | 59 | krb5_principal); |
60 | | | 60 | |
61 | PAM_EXTERN int | | 61 | PAM_EXTERN int |
62 | pam_sm_authenticate(pam_handle_t *pamh, int flags __unused, | | 62 | pam_sm_authenticate(pam_handle_t *pamh, int flags __unused, |
63 | int argc __unused, const char *argv[] __unused) | | 63 | int argc __unused, const char *argv[] __unused) |
64 | { | | 64 | { |
65 | krb5_context context; | | 65 | krb5_context context; |
66 | krb5_principal su_principal; | | 66 | krb5_principal su_principal; |
67 | const char *user; | | 67 | const char *user; |
68 | const void *ruser; | | 68 | const void *ruser; |
69 | char *su_principal_name; | | 69 | char *su_principal_name; |
70 | long rv; | | 70 | long rv; |
71 | int pamret; | | 71 | int pamret; |
72 | | | 72 | |
73 | pamret = pam_get_user(pamh, &user, NULL); | | 73 | pamret = pam_get_user(pamh, &user, NULL); |
74 | if (pamret != PAM_SUCCESS) | | 74 | if (pamret != PAM_SUCCESS) |
75 | return (pamret); | | 75 | return (pamret); |
76 | PAM_LOG("Got user: %s", user); | | 76 | PAM_LOG("Got user: %s", user); |
77 | pamret = pam_get_item(pamh, PAM_RUSER, &ruser); | | 77 | pamret = pam_get_item(pamh, PAM_RUSER, &ruser); |
78 | if (pamret != PAM_SUCCESS) | | 78 | if (pamret != PAM_SUCCESS) |
79 | return (pamret); | | 79 | return (pamret); |
80 | PAM_LOG("Got ruser: %s", (const char *)ruser); | | 80 | PAM_LOG("Got ruser: %s", (const char *)ruser); |
81 | rv = krb5_init_context(&context); | | 81 | rv = krb5_init_context(&context); |
82 | if (rv != 0) { | | 82 | if (rv != 0) { |
83 | log_krb5(context, rv, "krb5_init_context failed"); | | 83 | log_krb5(context, rv, "krb5_init_context failed"); |
84 | return (PAM_SERVICE_ERR); | | 84 | return (PAM_SERVICE_ERR); |
85 | } | | 85 | } |
86 | rv = get_su_principal(context, user, ruser, &su_principal_name, &su_principal); | | 86 | rv = get_su_principal(context, user, ruser, &su_principal_name, &su_principal); |
87 | if (rv != 0) | | 87 | if (rv != 0) |
88 | return (PAM_AUTH_ERR); | | 88 | return (PAM_AUTH_ERR); |
89 | PAM_LOG("kuserok: %s -> %s", su_principal_name, user); | | 89 | PAM_LOG("kuserok: %s -> %s", su_principal_name, user); |
90 | rv = krb5_kuserok(context, su_principal, user); | | 90 | rv = krb5_kuserok(context, su_principal, user); |
91 | pamret = rv ? auth_krb5(pamh, context, su_principal_name, su_principal) : PAM_AUTH_ERR; | | 91 | pamret = rv ? auth_krb5(pamh, context, su_principal_name, su_principal) : PAM_AUTH_ERR; |
92 | free(su_principal_name); | | 92 | free(su_principal_name); |
93 | krb5_free_principal(context, su_principal); | | 93 | krb5_free_principal(context, su_principal); |
94 | krb5_free_context(context); | | 94 | krb5_free_context(context); |
95 | return (pamret); | | 95 | return (pamret); |
96 | } | | 96 | } |
97 | | | 97 | |
98 | PAM_EXTERN int | | 98 | PAM_EXTERN int |
99 | pam_sm_setcred(pam_handle_t *pamh __unused, int flags __unused, | | 99 | pam_sm_setcred(pam_handle_t *pamh __unused, int flags __unused, |
100 | int ac __unused, const char *av[] __unused) | | 100 | int ac __unused, const char *av[] __unused) |
101 | { | | 101 | { |
102 | | | 102 | |
103 | return (PAM_SUCCESS); | | 103 | return (PAM_SUCCESS); |
104 | } | | 104 | } |
105 | | | 105 | |
106 | /* Authenticate using Kerberos 5. | | 106 | /* Authenticate using Kerberos 5. |
107 | * pamh -- The PAM handle. | | 107 | * pamh -- The PAM handle. |
108 | * context -- An initialized krb5_context. | | 108 | * context -- An initialized krb5_context. |
109 | * su_principal_name -- The target principal name, used only for password prompts. | | 109 | * su_principal_name -- The target principal name, used only for password prompts. |
110 | * If NULL, the password prompts will not include a principal | | 110 | * If NULL, the password prompts will not include a principal |
111 | * name. | | 111 | * name. |
112 | * su_principal -- The target krb5_principal. | | 112 | * su_principal -- The target krb5_principal. |
113 | * Note that a valid keytab in the default location with a host entry | | 113 | * Note that a valid keytab in the default location with a host entry |
114 | * must be available, and that the PAM application must have sufficient | | 114 | * must be available, and that the PAM application must have sufficient |
115 | * privileges to access it. | | 115 | * privileges to access it. |
116 | * Returns PAM_SUCCESS if authentication was successful, or an appropriate | | 116 | * Returns PAM_SUCCESS if authentication was successful, or an appropriate |
117 | * PAM error code if it was not. | | 117 | * PAM error code if it was not. |
118 | */ | | 118 | */ |
119 | static int | | 119 | static int |
120 | auth_krb5(pam_handle_t *pamh, krb5_context context, const char *su_principal_name, | | 120 | auth_krb5(pam_handle_t *pamh, krb5_context context, const char *su_principal_name, |
121 | krb5_principal su_principal) | | 121 | krb5_principal su_principal) |
122 | { | | 122 | { |
123 | krb5_creds creds; | | 123 | krb5_creds creds; |
124 | krb5_get_init_creds_opt *gic_opt; | | 124 | krb5_get_init_creds_opt *gic_opt; |
125 | krb5_verify_init_creds_opt vic_opt; | | 125 | krb5_verify_init_creds_opt vic_opt; |
126 | const char *pass; | | 126 | const char *pass; |
127 | char prompt[80]; | | 127 | char prompt[80]; |
128 | long rv; | | 128 | long rv; |
129 | int pamret; | | 129 | int pamret; |
130 | | | 130 | |
131 | rv = krb5_get_init_creds_opt_alloc(context, &gic_opt); | | 131 | rv = krb5_get_init_creds_opt_alloc(context, &gic_opt); |
132 | if (rv != 0) { | | 132 | if (rv != 0) { |
133 | log_krb5(context, rv, "krb5_get_init_creds_opt_alloc"); | | 133 | log_krb5(context, rv, "krb5_get_init_creds_opt_alloc"); |
134 | return (PAM_SERVICE_ERR); | | 134 | return (PAM_SERVICE_ERR); |
135 | } | | 135 | } |
136 | krb5_verify_init_creds_opt_init(&vic_opt); | | 136 | krb5_verify_init_creds_opt_init(&vic_opt); |
137 | if (su_principal_name != NULL) | | 137 | if (su_principal_name != NULL) |
138 | (void)snprintf(prompt, sizeof(prompt), PASSWORD_PROMPT, | | 138 | (void)snprintf(prompt, sizeof(prompt), PASSWORD_PROMPT, |
139 | su_principal_name); | | 139 | su_principal_name); |
140 | else | | 140 | else |
141 | (void)snprintf(prompt, sizeof(prompt), "Password:"); | | 141 | (void)snprintf(prompt, sizeof(prompt), "Password:"); |
142 | if (prompt == NULL) | | 142 | if (prompt == NULL) |
143 | return (PAM_BUF_ERR); | | 143 | return (PAM_BUF_ERR); |
144 | pass = NULL; | | 144 | pass = NULL; |
145 | pamret = pam_get_authtok(pamh, PAM_AUTHTOK, &pass, prompt); | | 145 | pamret = pam_get_authtok(pamh, PAM_AUTHTOK, &pass, prompt); |
146 | if (pamret != PAM_SUCCESS) | | 146 | if (pamret != PAM_SUCCESS) |
147 | return (pamret); | | 147 | return (pamret); |
148 | rv = krb5_get_init_creds_password(context, &creds, su_principal, | | 148 | rv = krb5_get_init_creds_password(context, &creds, su_principal, |
149 | pass, NULL, NULL, 0, NULL, gic_opt); | | 149 | pass, NULL, NULL, 0, NULL, gic_opt); |
150 | if (rv != 0) { | | 150 | if (rv != 0) { |
151 | log_krb5(context, rv, "krb5_get_init_creds_password"); | | 151 | log_krb5(context, rv, "krb5_get_init_creds_password"); |
152 | return (PAM_AUTH_ERR); | | 152 | return (PAM_AUTH_ERR); |
153 | } | | 153 | } |
154 | krb5_verify_init_creds_opt_set_ap_req_nofail(&vic_opt, 1); | | 154 | krb5_verify_init_creds_opt_set_ap_req_nofail(&vic_opt, 1); |
155 | rv = krb5_verify_init_creds(context, &creds, NULL, NULL, NULL, | | 155 | rv = krb5_verify_init_creds(context, &creds, NULL, NULL, NULL, |
156 | &vic_opt); | | 156 | &vic_opt); |
157 | krb5_free_cred_contents(context, &creds); | | 157 | krb5_free_cred_contents(context, &creds); |
158 | if (rv != 0) { | | 158 | if (rv != 0) { |
159 | log_krb5(context, rv, "krb5_verify_init_creds"); | | 159 | log_krb5(context, rv, "krb5_verify_init_creds"); |
160 | return (PAM_AUTH_ERR); | | 160 | return (PAM_AUTH_ERR); |
161 | } | | 161 | } |
162 | return (PAM_SUCCESS); | | 162 | return (PAM_SUCCESS); |
163 | } | | 163 | } |
164 | | | 164 | |
165 | static void | | 165 | static void |
166 | log_krb5(krb5_context ctx, krb5_error_code err, const char *fmt, ...) | | 166 | log_krb5(krb5_context ctx, krb5_error_code err, const char *fmt, ...) |
167 | { | | 167 | { |
168 | char b1[1024], b2[1024]; | | 168 | char b1[1024], b2[1024]; |
169 | const char *errtxt; | | 169 | const char *errtxt; |
170 | va_list ap; | | 170 | va_list ap; |
171 | | | 171 | |
172 | va_start(ap, fmt); | | 172 | va_start(ap, fmt); |
173 | vsnprintf(b1, sizeof(b1), fmt, ap); | | 173 | vsnprintf(b1, sizeof(b1), fmt, ap); |
174 | va_end(ap); | | 174 | va_end(ap); |
175 | if (ctx) | | 175 | if (ctx) |
176 | errtxt = krb5_get_error_message(ctx, err); | | 176 | errtxt = krb5_get_error_message(ctx, err); |
177 | else | | 177 | else |
178 | errtxt = NULL; | | 178 | errtxt = NULL; |
179 | if (errtxt != NULL) { | | 179 | if (errtxt != NULL) { |
180 | krb5_free_error_message(ctx, errtxt); | | 180 | krb5_free_error_message(ctx, errtxt); |
181 | snprintf(b2, sizeof(b2), "%s (%s)", b1, errtxt); | | 181 | snprintf(b2, sizeof(b2), "%s (%s)", b1, errtxt); |
182 | } else { | | 182 | } else { |
183 | snprintf(b2, sizeof(b1), "%s (unknown %d)", b1, (int)err); | | 183 | snprintf(b2, sizeof(b2), "%s (unknown %d)", b1, (int)err); |
184 | } | | 184 | } |
185 | PAM_LOG(b2); | | 185 | PAM_LOG(b2); |
186 | } | | 186 | } |
187 | | | 187 | |
188 | /* Determine the target principal given the current user and the target user. | | 188 | /* Determine the target principal given the current user and the target user. |
189 | * context -- An initialized krb5_context. | | 189 | * context -- An initialized krb5_context. |
190 | * target_user -- The target username. | | 190 | * target_user -- The target username. |
191 | * current_user -- The current username. | | 191 | * current_user -- The current username. |
192 | * su_principal_name -- (out) The target principal name. | | 192 | * su_principal_name -- (out) The target principal name. |
193 | * su_principal -- (out) The target krb5_principal. | | 193 | * su_principal -- (out) The target krb5_principal. |
194 | * When the target user is `root', the target principal will be a `root | | 194 | * When the target user is `root', the target principal will be a `root |
195 | * instance', e.g. `luser/root@REA.LM'. Otherwise, the target principal | | 195 | * instance', e.g. `luser/root@REA.LM'. Otherwise, the target principal |
196 | * will simply be the current user's default principal name. Note that | | 196 | * will simply be the current user's default principal name. Note that |
197 | * in any case, if KRB5CCNAME is set and a credentials cache exists, the | | 197 | * in any case, if KRB5CCNAME is set and a credentials cache exists, the |
198 | * principal name found there will be the `starting point', rather than | | 198 | * principal name found there will be the `starting point', rather than |
199 | * the ruser parameter. | | 199 | * the ruser parameter. |
200 | * | | 200 | * |
201 | * Returns 0 for success, or a com_err error code on failure. | | 201 | * Returns 0 for success, or a com_err error code on failure. |
202 | */ | | 202 | */ |
203 | static long | | 203 | static long |
204 | get_su_principal(krb5_context context, const char *target_user, const char *current_user, | | 204 | get_su_principal(krb5_context context, const char *target_user, const char *current_user, |
205 | char **su_principal_name, krb5_principal *su_principal) | | 205 | char **su_principal_name, krb5_principal *su_principal) |
206 | { | | 206 | { |
207 | krb5_principal default_principal; | | 207 | krb5_principal default_principal; |
208 | krb5_ccache ccache; | | 208 | krb5_ccache ccache; |
209 | char *principal_name, *ccname, *p; | | 209 | char *principal_name, *ccname, *p; |
210 | long rv; | | 210 | long rv; |
211 | uid_t euid, ruid; | | 211 | uid_t euid, ruid; |
212 | | | 212 | |
213 | *su_principal = NULL; | | 213 | *su_principal = NULL; |
214 | default_principal = NULL; | | 214 | default_principal = NULL; |
215 | /* Unless KRB5CCNAME was explicitly set, we won't really be able | | 215 | /* Unless KRB5CCNAME was explicitly set, we won't really be able |
216 | * to look at the credentials cache since krb5_cc_default will | | 216 | * to look at the credentials cache since krb5_cc_default will |
217 | * look at getuid(). | | 217 | * look at getuid(). |
218 | */ | | 218 | */ |
219 | ruid = getuid(); | | 219 | ruid = getuid(); |
220 | euid = geteuid(); | | 220 | euid = geteuid(); |
221 | rv = seteuid(ruid); | | 221 | rv = seteuid(ruid); |
222 | if (rv != 0) | | 222 | if (rv != 0) |
223 | return (errno); | | 223 | return (errno); |
224 | p = getenv("KRB5CCNAME"); | | 224 | p = getenv("KRB5CCNAME"); |
225 | if (p != NULL) | | 225 | if (p != NULL) |
226 | ccname = strdup(p); | | 226 | ccname = strdup(p); |
227 | else | | 227 | else |
228 | (void)asprintf(&ccname, "%s%lu", KRB5_DEFAULT_CCROOT, (unsigned long)ruid); | | 228 | (void)asprintf(&ccname, "%s%lu", KRB5_DEFAULT_CCROOT, (unsigned long)ruid); |
229 | if (ccname == NULL) | | 229 | if (ccname == NULL) |
230 | return (errno); | | 230 | return (errno); |
231 | rv = krb5_cc_resolve(context, ccname, &ccache); | | 231 | rv = krb5_cc_resolve(context, ccname, &ccache); |
232 | free(ccname); | | 232 | free(ccname); |
233 | if (rv == 0) { | | 233 | if (rv == 0) { |
234 | rv = krb5_cc_get_principal(context, ccache, &default_principal); | | 234 | rv = krb5_cc_get_principal(context, ccache, &default_principal); |
235 | krb5_cc_close(context, ccache); | | 235 | krb5_cc_close(context, ccache); |
236 | if (rv != 0) | | 236 | if (rv != 0) |
237 | default_principal = NULL; /* just to be safe */ | | 237 | default_principal = NULL; /* just to be safe */ |
238 | } | | 238 | } |
239 | rv = seteuid(euid); | | 239 | rv = seteuid(euid); |
240 | if (rv != 0) | | 240 | if (rv != 0) |
241 | return (errno); | | 241 | return (errno); |
242 | if (default_principal == NULL) { | | 242 | if (default_principal == NULL) { |
243 | rv = krb5_make_principal(context, &default_principal, NULL, current_user, NULL); | | 243 | rv = krb5_make_principal(context, &default_principal, NULL, current_user, NULL); |
244 | if (rv != 0) { | | 244 | if (rv != 0) { |
245 | PAM_LOG("Could not determine default principal name."); | | 245 | PAM_LOG("Could not determine default principal name."); |
246 | return (rv); | | 246 | return (rv); |
247 | } | | 247 | } |
248 | } | | 248 | } |
249 | /* Now that we have some principal, if the target account is | | 249 | /* Now that we have some principal, if the target account is |
250 | * `root', then transform it into a `root' instance, e.g. | | 250 | * `root', then transform it into a `root' instance, e.g. |
251 | * `user@REA.LM' -> `user/root@REA.LM'. | | 251 | * `user@REA.LM' -> `user/root@REA.LM'. |
252 | */ | | 252 | */ |
253 | rv = krb5_unparse_name(context, default_principal, &principal_name); | | 253 | rv = krb5_unparse_name(context, default_principal, &principal_name); |
254 | krb5_free_principal(context, default_principal); | | 254 | krb5_free_principal(context, default_principal); |
255 | if (rv != 0) { | | 255 | if (rv != 0) { |
256 | log_krb5(context, rv, "krb5_unparse_name"); | | 256 | log_krb5(context, rv, "krb5_unparse_name"); |
257 | return (rv); | | 257 | return (rv); |
258 | } | | 258 | } |
259 | PAM_LOG("Default principal name: %s", principal_name); | | 259 | PAM_LOG("Default principal name: %s", principal_name); |
260 | if (strcmp(target_user, superuser) == 0) { | | 260 | if (strcmp(target_user, superuser) == 0) { |
261 | p = strrchr(principal_name, '@'); | | 261 | p = strrchr(principal_name, '@'); |
262 | if (p == NULL) { | | 262 | if (p == NULL) { |
263 | PAM_LOG("malformed principal name `%s'", principal_name); | | 263 | PAM_LOG("malformed principal name `%s'", principal_name); |
264 | free(principal_name); | | 264 | free(principal_name); |
265 | return (rv); | | 265 | return (rv); |
266 | } | | 266 | } |
267 | *p++ = '\0'; | | 267 | *p++ = '\0'; |
268 | *su_principal_name = NULL; | | 268 | *su_principal_name = NULL; |
269 | (void)asprintf(su_principal_name, "%s/%s@%s", principal_name, superuser, p); | | 269 | (void)asprintf(su_principal_name, "%s/%s@%s", principal_name, superuser, p); |
270 | free(principal_name); | | 270 | free(principal_name); |
271 | } else | | 271 | } else |
272 | *su_principal_name = principal_name; | | 272 | *su_principal_name = principal_name; |
273 | | | 273 | |
274 | if (*su_principal_name == NULL) | | 274 | if (*su_principal_name == NULL) |
275 | return (errno); | | 275 | return (errno); |
276 | rv = krb5_parse_name(context, *su_principal_name, &default_principal); | | 276 | rv = krb5_parse_name(context, *su_principal_name, &default_principal); |
277 | if (rv != 0) { | | 277 | if (rv != 0) { |
278 | log_krb5(context, rv, "krb5_parse_name `%s'", | | 278 | log_krb5(context, rv, "krb5_parse_name `%s'", |
279 | *su_principal_name); | | 279 | *su_principal_name); |
280 | return (rv); | | 280 | return (rv); |
281 | } | | 281 | } |
282 | PAM_LOG("Target principal name: %s", *su_principal_name); | | 282 | PAM_LOG("Target principal name: %s", *su_principal_name); |
283 | *su_principal = default_principal; | | 283 | *su_principal = default_principal; |
284 | return (0); | | 284 | return (0); |
285 | } | | 285 | } |
286 | | | 286 | |
287 | PAM_MODULE_ENTRY("pam_ksu"); | | 287 | PAM_MODULE_ENTRY("pam_ksu"); |