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