cc678aaef449a7deee8a5db05f1550ae1267b560
[openafs.git] / src / kauth / user.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /* This file provides the easiest, turn-key interface to the authication
11  * package. */
12
13 #include <afsconfig.h>
14 #include <afs/param.h>
15 #include <afs/stds.h>
16
17 #include <roken.h>
18
19 #include <hcrypto/des.h>
20 #include <hcrypto/ui.h>
21
22 #include <afs/com_err.h>
23 #include <afs/cellconfig.h>
24 #include <afs/auth.h>
25 #include <afs/ptint.h>
26 #include <afs/pterror.h>
27 #include <afs/ptuser.h>
28 #include <afs/ptserver.h>
29 #include <afs/afsutil.h>
30 #include <afs/sys_prototypes.h>
31
32 #include <rx/rx.h>
33 #include <rx/rx_globals.h>
34 #include <rx/rxkad.h>           /* max ticket lifetime */
35 #include <rx/rxkad_convert.h>
36
37 #include "kauth.h"
38 #include "kautils.h"
39 #include <afs/ktc.h>
40
41 afs_int32
42 GetTickets(char *name, char *instance, char *realm,
43            struct ktc_encryptionKey * key, Date lifetime,
44            afs_int32 * pwexpires, afs_int32 flags)
45 {
46     afs_int32 code;
47
48     code = ka_GetAuthToken(name, instance, realm, key, lifetime, pwexpires);
49     memset(key, 0, sizeof(*key));
50     if (code)
51         return code;
52     code = ka_GetAFSTicket(name, instance, realm, lifetime, flags);
53     return code;
54 }
55
56 /*
57  * Requires that you already possess a TGT.
58  */
59 afs_int32
60 ka_GetAFSTicket(char *name, char *instance, char *realm, Date lifetime,
61                 afs_int32 flags)
62 {
63     afs_int32 code;
64     struct ktc_token token;
65     struct ktc_principal server, client;
66
67     code = ka_GetServerToken("afs", "", realm, lifetime, &token, /*new */ 1,
68                              /*dosetpag */ flags);
69     if (code)
70         return code;
71     if (ktc_OldPioctl()) {
72         int local;
73         char username[MAXKTCNAMELEN];
74         afs_int32 viceId;
75         int len;
76         char *whoami = "UserAuthenticate: ptserver";
77
78         strcpy(server.name, "afs");
79         strcpy(server.instance, "");
80         code = ka_ExpandCell(realm, server.cell, &local);
81         if (code)
82             return code;
83         code = pr_Initialize(0, AFSDIR_CLIENT_ETC_DIRPATH, server.cell);
84         if (code) {
85             afs_com_err(whoami, code, "initializing ptserver in cell '%s'",
86                     server.cell);
87             return 0;
88         }
89         len = strlen(name);
90         if (instance[0])
91             len += strlen(instance) + 1;
92         if (len >= sizeof(username)) {
93             fprintf(stderr, "user's name '%s'.'%s' would be too large\n",
94                     name, instance);
95             return 0;
96         }
97         strcpy(username, name);
98         if (instance[0]) {
99             strcat(username, ".");
100             strcat(username, instance);
101         }
102         code = pr_SNameToId(username, &viceId);
103         /* Before going further, shutdown the pr ubik connection */
104         pr_End();
105         if ((code == 0) && (viceId == ANONYMOUSID))
106             code = PRNOENT;
107         if (code) {
108             afs_com_err(whoami, code, "translating %s to id", username);
109             return 0;
110         }
111
112         sprintf(client.name, "AFS ID %d", viceId);
113         strcpy(client.instance, "");
114         strcpy(client.cell, server.cell);
115         code = ktc_SetToken(&server, &token, &client, /*dosetpag */ 0);
116         if (code)
117             return code;
118     }
119     return code;
120 }
121
122 #ifdef ka_UserAuthenticate
123 #undef ka_UserAuthenticate
124 #endif
125
126 afs_int32
127 ka_UserAuthenticateGeneral(afs_int32 flags, char *name, char *instance,
128                            char *realm, char *password, Date lifetime,
129                            afs_int32 * password_expires,        /* days 'til, or don't change if not set */
130                            afs_int32 spare2, char **reasonP)
131 {
132     int remainingTime = 0;
133     struct ktc_encryptionKey key;
134     afs_int32 code, dosetpag = 0;
135
136     if (reasonP)
137         *reasonP = "";
138     if ((flags & KA_USERAUTH_VERSION_MASK) != KA_USERAUTH_VERSION)
139         return KAOLDINTERFACE;
140     if ((strcmp(name, "root") == 0) && (instance == 0)) {
141         if (reasonP)
142             *reasonP = "root is only authenticated locally";
143         return KANOENT;
144     }
145     code = ka_Init(0);
146     if (code)
147         return code;
148
149     ka_StringToKey(password, realm, &key);
150
151 /*
152  * alarm is set by kpasswd only so ignore for
153  * NT
154  */
155
156 #ifndef AFS_NT40_ENV
157     {                           /* Rx uses timers, save to be safe */
158         if (rx_socket) {
159             /* don't reset alarms, rx already running */
160             remainingTime = 0;
161         } else
162             remainingTime = alarm(0);
163     }
164 #endif
165
166 #if !defined(AFS_NT40_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_USR_LINUX20_ENV) && (!defined(AFS_XBSD_ENV) || defined(AFS_FBSD_ENV))
167     /* handle smoothly the case where no AFS system calls exists (yet) */
168     (void)signal(SIGSYS, SIG_IGN);
169 #endif
170 #ifdef  AFS_DECOSF_ENV
171     (void)signal(SIGTRAP, SIG_IGN);
172 #endif /* AFS_DECOSF_ENV */
173     if (instance == 0)
174         instance = "";
175     if (flags & KA_USERAUTH_ONLY_VERIFY) {
176         code = ka_VerifyUserToken(name, instance, realm, &key);
177         if (code == KABADREQUEST) {
178             DES_string_to_key(password, ktc_to_cblockptr(&key));
179             code = ka_VerifyUserToken(name, instance, realm, &key);
180         }
181     } else {
182 #ifdef AFS_DUX40_ENV
183         if (flags & KA_USERAUTH_DOSETPAG)
184             afs_setpag();
185 #else
186 #if !defined(AFS_NT40_ENV)
187         if (flags & KA_USERAUTH_DOSETPAG)
188             setpag();
189 #endif
190 #endif
191         if (flags & KA_USERAUTH_DOSETPAG2)
192             dosetpag = 1;
193 #ifdef AFS_KERBEROS_ENV
194         if ((flags & KA_USERAUTH_DOSETPAG) || dosetpag)
195             ktc_newpag();
196 #endif
197         if (lifetime == 0)
198             lifetime = MAXKTCTICKETLIFETIME;
199         code =
200             GetTickets(name, instance, realm, &key, lifetime,
201                        password_expires, dosetpag);
202         if (code == KABADREQUEST) {
203             DES_string_to_key(password, ktc_to_cblockptr(&key));
204             code =
205                 GetTickets(name, instance, realm, &key, lifetime,
206                            password_expires, dosetpag);
207         }
208     }
209
210 #ifndef AFS_NT40_ENV
211     if (remainingTime) {
212         pr_End();
213         rx_Finalize();
214         alarm(remainingTime);   /* restore timer, if any */
215     }
216 #endif
217
218     if (code && reasonP)
219         switch (code) {
220         case KABADREQUEST:
221             *reasonP = "password was incorrect";
222             break;
223         case KAUBIKCALL:
224             *reasonP = "Authentication Server was unavailable";
225             break;
226         default:
227             *reasonP = (char *)afs_error_message(code);
228         }
229     return code;
230 }
231
232 /* For backward compatibility */
233 afs_int32
234 ka_UserAuthenticate(char *name, char *instance, char *realm, char *password,
235                     int doSetPAG, char **reasonP)
236 {
237     return ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION +
238                                       ((doSetPAG) ? KA_USERAUTH_DOSETPAG : 0),
239                                       name, instance, realm, password,
240                                       /*lifetime */ 0, /*spare1,2 */ 0, 0,
241                                       reasonP);
242 }
243
244 afs_int32
245 ka_UserReadPassword(char *prompt, char *password, int plen, char **reasonP)
246 {
247     afs_int32 code = 0;
248
249     if (reasonP)
250         *reasonP = "";
251     code = ka_Init(0);
252     if (code)
253         return code;
254     code = UI_UTIL_read_pw_string(password, plen, prompt, 0);
255     if (code)
256         code = KAREADPW;
257     else if (strlen(password) == 0)
258         code = KANULLPASSWORD;
259     else
260         return 0;
261
262     if (reasonP) {
263         *reasonP = (char *)afs_error_message(code);
264     }
265     return code;
266 }
267
268 afs_int32
269 ka_VerifyUserPassword(afs_int32 version, char *name, char *instance,
270                       char *realm, char *password, int spare, char **reasonP)
271 {
272     afs_int32 pwexpires;
273
274     version &= KA_USERAUTH_VERSION_MASK;
275     return ka_UserAuthenticateGeneral(version | KA_USERAUTH_ONLY_VERIFY, name,
276                                       instance, realm, password, 0,
277                                       &pwexpires, spare, reasonP);
278 }