1.1.5
by Russ Allbery
Import upstream version 3.5 |
1 |
/*
|
2 |
* Implements the PAM password group API (pam_sm_chauthtok).
|
|
3 |
*
|
|
1.2.3
by Russ Allbery
Import upstream version 4.3 |
4 |
* Copyright 2005, 2006, 2007, 2008, 2009 Russ Allbery <rra@stanford.edu>
|
1.1.8
by Russ Allbery
Import upstream version 3.10 |
5 |
* Copyright 2005 Andres Salomon <dilinger@debian.org>
|
6 |
* Copyright 1999, 2000 Frank Cusack <fcusack@fcusack.com>
|
|
1.1.10
by Steve Langasek
Import upstream version 3.13 |
7 |
*
|
1.1.8
by Russ Allbery
Import upstream version 3.10 |
8 |
* See LICENSE for licensing terms.
|
1.1.5
by Russ Allbery
Import upstream version 3.5 |
9 |
*/
|
10 |
||
11 |
/* Get declarations for the password functions. */
|
|
12 |
#define PAM_SM_PASSWORD
|
|
13 |
||
1.1.14
by Russ Allbery
Import upstream version 4.1 |
14 |
#include <config.h> |
15 |
#include <portable/pam.h> |
|
1.1.5
by Russ Allbery
Import upstream version 3.5 |
16 |
|
17 |
#include <errno.h> |
|
18 |
#include <string.h> |
|
19 |
||
1.1.14
by Russ Allbery
Import upstream version 4.1 |
20 |
#include <internal.h> |
1.1.5
by Russ Allbery
Import upstream version 3.5 |
21 |
|
1.1.9
by Russ Allbery
Import upstream version 3.11 |
22 |
|
23 |
/*
|
|
24 |
* The main PAM interface for password changing.
|
|
25 |
*/
|
|
1.1.5
by Russ Allbery
Import upstream version 3.5 |
26 |
int
|
27 |
pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) |
|
28 |
{
|
|
29 |
struct context *ctx = NULL; |
|
30 |
struct pam_args *args; |
|
31 |
int pamret = PAM_SUCCESS; |
|
32 |
int status; |
|
1.1.6
by Russ Allbery
Import upstream version 3.8 |
33 |
PAM_CONST char *user; |
1.1.5
by Russ Allbery
Import upstream version 3.5 |
34 |
char *pass = NULL; |
35 |
||
36 |
args = pamk5_args_parse(pamh, flags, argc, argv); |
|
37 |
if (args == NULL) { |
|
1.1.14
by Russ Allbery
Import upstream version 4.1 |
38 |
pamk5_crit(NULL, "cannot allocate memory: %s", strerror(errno)); |
1.1.5
by Russ Allbery
Import upstream version 3.5 |
39 |
pamret = PAM_AUTHTOK_ERR; |
40 |
goto done; |
|
41 |
}
|
|
42 |
pamret = pamk5_context_fetch(args); |
|
43 |
ENTRY(args, flags); |
|
44 |
||
45 |
/* We only support password changes. */
|
|
46 |
if (!(flags & PAM_UPDATE_AUTHTOK) && !(flags & PAM_PRELIM_CHECK)) { |
|
1.1.14
by Russ Allbery
Import upstream version 4.1 |
47 |
pamk5_err(args, "invalid pam_chauthtok flags %d", flags); |
1.1.5
by Russ Allbery
Import upstream version 3.5 |
48 |
pamret = PAM_AUTHTOK_ERR; |
49 |
goto done; |
|
50 |
}
|
|
51 |
||
1.1.14
by Russ Allbery
Import upstream version 4.1 |
52 |
/*
|
53 |
* Check whether we should ignore this user.
|
|
54 |
*
|
|
55 |
* If we do ignore this user, and we're not in the preliminary check
|
|
56 |
* phase, still prompt the user for the new password, but suppress our
|
|
57 |
* banner. This is a little strange, but it allows another module to be
|
|
58 |
* stacked behind pam-krb5 with use_authtok and have it still work for
|
|
59 |
* ignored users.
|
|
60 |
*
|
|
61 |
* We ignore the return status when prompting for the new password in this
|
|
62 |
* case. The worst thing that can happen is to fail to get the password,
|
|
63 |
* in which case the other module will fail (or might even not care).
|
|
64 |
*/
|
|
1.1.5
by Russ Allbery
Import upstream version 3.5 |
65 |
if (args->ignore_root || args->minimum_uid > 0) { |
1.1.6
by Russ Allbery
Import upstream version 3.8 |
66 |
status = pam_get_user(pamh, &user, NULL); |
67 |
if (status == PAM_SUCCESS && pamk5_should_ignore(args, user)) { |
|
1.1.14
by Russ Allbery
Import upstream version 4.1 |
68 |
if (flags & PAM_UPDATE_AUTHTOK) { |
69 |
if (args->banner != NULL) { |
|
70 |
free(args->banner); |
|
71 |
args->banner = NULL; |
|
72 |
}
|
|
73 |
pamk5_password_prompt(args, NULL); |
|
74 |
}
|
|
13.1.1
by Russ Allbery
Return PAM_IGNORE for ignored users in pam_chauthtok instead of |
75 |
pamret = PAM_IGNORE; |
1.1.5
by Russ Allbery
Import upstream version 3.5 |
76 |
goto done; |
77 |
}
|
|
78 |
}
|
|
79 |
||
80 |
/*
|
|
81 |
* If we weren't able to find an existing context to use, we're going
|
|
82 |
* into this fresh and need to create a new context.
|
|
83 |
*/
|
|
84 |
if (args->ctx == NULL) { |
|
85 |
pamret = pamk5_context_new(args); |
|
86 |
if (pamret != PAM_SUCCESS) { |
|
1.1.14
by Russ Allbery
Import upstream version 4.1 |
87 |
pamk5_debug_pam(args, pamret, "creating context failed"); |
1.1.5
by Russ Allbery
Import upstream version 3.5 |
88 |
pamret = PAM_AUTHTOK_ERR; |
89 |
goto done; |
|
90 |
}
|
|
1.1.6
by Russ Allbery
Import upstream version 3.8 |
91 |
pamret = pam_set_data(pamh, "pam_krb5", args->ctx, |
92 |
pamk5_context_destroy); |
|
1.1.5
by Russ Allbery
Import upstream version 3.5 |
93 |
if (pamret != PAM_SUCCESS) { |
1.1.14
by Russ Allbery
Import upstream version 4.1 |
94 |
pamk5_err_pam(args, pamret, "cannot set context data"); |
1.1.5
by Russ Allbery
Import upstream version 3.5 |
95 |
pamret = PAM_AUTHTOK_ERR; |
96 |
goto done; |
|
97 |
}
|
|
98 |
}
|
|
99 |
ctx = args->ctx; |
|
100 |
||
1.1.9
by Russ Allbery
Import upstream version 3.11 |
101 |
/* Tell the user what's going on if we're handling an expiration. */
|
102 |
if (ctx->expired && ctx->creds == NULL) |
|
103 |
pamk5_conv(args, "Password expired. You must change it now.", |
|
104 |
PAM_TEXT_INFO, NULL); |
|
105 |
||
1.1.13
by Russ Allbery
Import upstream version 4.0 |
106 |
/*
|
107 |
* Do the password change. This may only get tickets if we're doing the
|
|
108 |
* preliminary check phase.
|
|
109 |
*/
|
|
1.1.9
by Russ Allbery
Import upstream version 3.11 |
110 |
pamret = pamk5_password_change(args, !(flags & PAM_UPDATE_AUTHTOK)); |
111 |
if (!(flags & PAM_UPDATE_AUTHTOK)) |
|
112 |
goto done; |
|
1.1.5
by Russ Allbery
Import upstream version 3.5 |
113 |
|
114 |
/*
|
|
1.1.9
by Russ Allbery
Import upstream version 3.11 |
115 |
* If we were handling a password change for an expired password, now
|
116 |
* try to get a ticket cache with the new password.
|
|
1.1.5
by Russ Allbery
Import upstream version 3.5 |
117 |
*/
|
1.1.9
by Russ Allbery
Import upstream version 3.11 |
118 |
if (pamret == PAM_SUCCESS && ctx->expired) { |
119 |
krb5_creds *creds = NULL; |
|
120 |
||
121 |
pamk5_debug(args, "obtaining credentials with new password"); |
|
1.1.13
by Russ Allbery
Import upstream version 4.0 |
122 |
args->force_first_pass = 1; |
1.1.9
by Russ Allbery
Import upstream version 3.11 |
123 |
pamret = pamk5_password_auth(args, NULL, &creds); |
1.1.5
by Russ Allbery
Import upstream version 3.5 |
124 |
if (pamret != PAM_SUCCESS) |
125 |
goto done; |
|
1.1.9
by Russ Allbery
Import upstream version 3.11 |
126 |
pamret = pamk5_cache_init_random(args, creds); |
1.1.5
by Russ Allbery
Import upstream version 3.5 |
127 |
}
|
128 |
||
129 |
done: |
|
1.1.9
by Russ Allbery
Import upstream version 3.11 |
130 |
if (pamret != PAM_SUCCESS) { |
131 |
if (pamret == PAM_SERVICE_ERR || pamret == PAM_AUTH_ERR) |
|
132 |
pamret = PAM_AUTHTOK_ERR; |
|
133 |
if (pamret == PAM_AUTHINFO_UNAVAIL) |
|
134 |
pamret = PAM_AUTHTOK_ERR; |
|
135 |
}
|
|
1.1.5
by Russ Allbery
Import upstream version 3.5 |
136 |
EXIT(args, pamret); |
137 |
if (pass != NULL) { |
|
138 |
memset(pass, 0, strlen(pass)); |
|
139 |
free(pass); |
|
140 |
}
|
|
141 |
pamk5_args_free(args); |
|
142 |
return pamret; |
|
143 |
}
|