90107cc18ca759df4c5b35dc38730d68ea12e10b
[openafs.git] / src / kauth / katoken.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 /* These routines provide an interface to the token cache maintained by the
11    kernel.  Principally it handles cache misses by requesting the desired token
12    from the AuthServer. */
13
14 #include <afsconfig.h>
15 #include <afs/param.h>
16
17 #include <roken.h>
18
19 #ifdef UKERNEL
20 # include "afsincludes.h"
21 #endif
22
23 #include <afs/stds.h>
24 #include <sys/types.h>
25 #include <rx/xdr.h>
26 #include <afs/pthread_glock.h>
27 #ifdef AFS_NT40_ENV
28 #include <winsock2.h>
29 #else
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #endif
33 #include <string.h>
34 /* netinet/in.h and cellconfig.h  are needed together */
35 #include <afs/cellconfig.h>
36     /* these are needed together */
37 #include <lock.h>
38 #include <ubik.h>
39
40 #include "kauth.h"
41 #include "kautils.h"
42 #include <afs/auth.h>
43
44
45 afs_int32
46 ka_GetAuthToken(char *name, char *instance, char *cell,
47                 struct ktc_encryptionKey * key, afs_int32 lifetime,
48                 afs_int32 * pwexpires)
49 {
50     afs_int32 code;
51     struct ubik_client *conn;
52     afs_int32 now = time(0);
53     struct ktc_token token;
54     char cellname[MAXKTCREALMLEN];
55     char realm[MAXKTCREALMLEN];
56     struct ktc_principal client, server;
57
58     LOCK_GLOBAL_MUTEX;
59     code = ka_ExpandCell(cell, cellname, 0 /*local */ );
60     if (code) {
61         UNLOCK_GLOBAL_MUTEX;
62         return code;
63     }
64     cell = cellname;
65
66     /* get an unauthenticated connection to desired cell */
67     code = ka_AuthServerConn(cell, KA_AUTHENTICATION_SERVICE, 0, &conn);
68     if (code) {
69         UNLOCK_GLOBAL_MUTEX;
70         return code;
71     }
72     code =
73         ka_Authenticate(name, instance, cell, conn,
74                         KA_TICKET_GRANTING_SERVICE, key, now, now + lifetime,
75                         &token, pwexpires);
76     if (code) {
77         UNLOCK_GLOBAL_MUTEX;
78         return code;
79     }
80     code = ubik_ClientDestroy(conn);
81     if (code) {
82         UNLOCK_GLOBAL_MUTEX;
83         return code;
84     }
85
86     code = ka_CellToRealm(cell, realm, 0 /*local */ );
87     if (code) {
88         UNLOCK_GLOBAL_MUTEX;
89         return code;
90     }
91     strcpy(client.name, name);
92     strcpy(client.instance, instance);
93     strncpy(client.cell, cell, sizeof(client.cell));
94     strcpy(server.name, KA_TGS_NAME);
95     strcpy(server.instance, realm);
96     strcpy(server.cell, cell);
97     code = ktc_SetToken(&server, &token, &client, 0);
98     UNLOCK_GLOBAL_MUTEX;
99     return code;
100 }
101
102 afs_int32
103 ka_GetServerToken(char *name, char *instance, char *cell, Date lifetime,
104                   struct ktc_token * token, int new, int dosetpag)
105 {
106     afs_int32 code;
107     struct ubik_client *conn;
108     afs_int32 now = time(0);
109     struct ktc_token auth_token;
110     struct ktc_token cell_token;
111     struct ktc_principal server, auth_server, client;
112     char *localCell = ka_LocalCell();
113     char cellname[MAXKTCREALMLEN];
114     char realm[MAXKTCREALMLEN];
115     char authDomain[MAXKTCREALMLEN];
116     int local;
117
118     LOCK_GLOBAL_MUTEX;
119     code = ka_ExpandCell(cell, cellname, 0 /*local */ );
120     if (code) {
121         UNLOCK_GLOBAL_MUTEX;
122         return code;
123     }
124     cell = cellname;
125
126     strcpy(server.name, name);
127     strcpy(server.instance, instance);
128     lcstring(server.cell, cell, sizeof(server.cell));
129     if (!new) {
130         code =
131             ktc_GetToken(&server, token, sizeof(struct ktc_token), &client);
132         if (!code) {
133             UNLOCK_GLOBAL_MUTEX;
134             return 0;
135         }
136     }
137
138     code = ka_CellToRealm(cell, realm, &local);
139     if (code) {
140         UNLOCK_GLOBAL_MUTEX;
141         return code;
142     }
143
144     /* get TGS ticket for proper realm */
145     strcpy(auth_server.name, KA_TGS_NAME);
146     strcpy(auth_server.instance, realm);
147     lcstring(auth_server.cell, realm, sizeof(auth_server.cell));
148     strcpy(authDomain, realm);
149     code =
150         ktc_GetToken(&auth_server, &auth_token, sizeof(auth_token), &client);
151     if (code && !local) {       /* try for remotely authenticated ticket */
152         strcpy(auth_server.cell, localCell);
153         strcpy(authDomain, "");
154         code =
155             ktc_GetToken(&auth_server, &auth_token, sizeof(auth_token),
156                          &client);
157     }
158
159     if (code && local) {
160         UNLOCK_GLOBAL_MUTEX;
161         return code;
162     } else if (code) {
163         /* here we invoke the inter-cell mechanism */
164
165         /* get local auth ticket */
166         ucstring(auth_server.instance, localCell,
167                  sizeof(auth_server.instance));
168         strcpy(auth_server.cell, localCell);
169         code =
170             ktc_GetToken(&auth_server, &cell_token, sizeof(cell_token),
171                          &client);
172         if (code) {
173             UNLOCK_GLOBAL_MUTEX;
174             return code;
175         }
176         /* get a connection to the local cell */
177         if ((code =
178              ka_AuthServerConn(localCell, KA_TICKET_GRANTING_SERVICE, 0,
179                                &conn))) {
180             UNLOCK_GLOBAL_MUTEX;
181             return code;
182         }
183         /* get foreign auth ticket */
184         if ((code =
185              ka_GetToken(KA_TGS_NAME, realm, localCell, client.name,
186                          client.instance, conn, now, now + lifetime,
187                          &cell_token, "" /* local auth domain */ ,
188                          &auth_token))) {
189             UNLOCK_GLOBAL_MUTEX;
190             return code;
191         }
192         code = ubik_ClientDestroy(conn);
193         if (code) {
194             UNLOCK_GLOBAL_MUTEX;
195             return code;
196         }
197         conn = 0;
198
199         /* save foreign auth ticket */
200         strcpy(auth_server.instance, realm);
201         lcstring(auth_server.cell, localCell, sizeof(auth_server.cell));
202         ucstring(authDomain, localCell, sizeof(authDomain));
203         if ((code = ktc_SetToken(&auth_server, &auth_token, &client, 0))) {
204             UNLOCK_GLOBAL_MUTEX;
205             return code;
206         }
207     }
208
209     if ((code =
210          ka_AuthServerConn(cell, KA_TICKET_GRANTING_SERVICE, 0, &conn))) {
211         UNLOCK_GLOBAL_MUTEX;
212         return code;
213     }
214     if ((code =
215          ka_GetToken(name, instance, cell, client.name, client.instance, conn,
216                      now, now + lifetime, &auth_token, authDomain, token))) {
217         UNLOCK_GLOBAL_MUTEX;
218         return code;
219     }
220     code = ubik_ClientDestroy(conn);
221     if (code) {
222         UNLOCK_GLOBAL_MUTEX;
223         return code;
224     }
225
226     if ((code =
227          ktc_SetToken(&server, token, &client,
228                       dosetpag ? AFS_SETTOK_SETPAG : 0))) {
229         UNLOCK_GLOBAL_MUTEX;
230         return code;
231     }
232     UNLOCK_GLOBAL_MUTEX;
233     return 0;
234 }
235
236 afs_int32
237 ka_GetAdminToken(char *name, char *instance, char *cell,
238                  struct ktc_encryptionKey * key, afs_int32 lifetime,
239                  struct ktc_token * token, int new)
240 {
241     int code;
242     struct ubik_client *conn;
243     afs_int32 now = time(0);
244     struct ktc_principal server, client;
245     struct ktc_token localToken;
246     char cellname[MAXKTCREALMLEN];
247
248     LOCK_GLOBAL_MUTEX;
249     code = ka_ExpandCell(cell, cellname, 0 /*local */ );
250     if (code) {
251         UNLOCK_GLOBAL_MUTEX;
252         return code;
253     }
254     cell = cellname;
255
256     if (token == 0)
257         token = &localToken;    /* in case caller doesn't want token */
258
259     strcpy(server.name, KA_ADMIN_NAME);
260     strcpy(server.instance, KA_ADMIN_INST);
261     strncpy(server.cell, cell, sizeof(server.cell));
262     if (!new) {
263         code =
264             ktc_GetToken(&server, token, sizeof(struct ktc_token), &client);
265         if (code == 0) {
266             UNLOCK_GLOBAL_MUTEX;
267             return 0;
268         }
269     }
270
271     if ((name == 0) || (key == 0)) {
272         /* just lookup in cache don't get new one */
273         UNLOCK_GLOBAL_MUTEX;
274         return KANOTICKET;
275     }
276
277     /* get an unauthenticated connection to desired cell */
278     code = ka_AuthServerConn(cell, KA_AUTHENTICATION_SERVICE, 0, &conn);
279     if (code) {
280         UNLOCK_GLOBAL_MUTEX;
281         return code;
282     }
283     code =
284         ka_Authenticate(name, instance, cell, conn, KA_MAINTENANCE_SERVICE,
285                         key, now, now + lifetime, token, 0);
286     (void)ubik_ClientDestroy(conn);
287     if (code) {
288         UNLOCK_GLOBAL_MUTEX;
289         return code;
290     }
291
292     strcpy(client.name, name);
293     strcpy(client.instance, instance);
294     strncpy(client.cell, cell, sizeof(client.cell));
295     code = ktc_SetToken(&server, token, &client, 0);
296     UNLOCK_GLOBAL_MUTEX;
297     return code;
298 }
299
300
301 afs_int32
302 ka_VerifyUserToken(char *name, char *instance, char *cell,
303                    struct ktc_encryptionKey * key)
304 {
305     afs_int32 code;
306     struct ubik_client *conn;
307     afs_int32 now = time(0);
308     struct ktc_token token;
309     char cellname[MAXKTCREALMLEN];
310     afs_int32 pwexpires;
311
312     LOCK_GLOBAL_MUTEX;
313     code = ka_ExpandCell(cell, cellname, 0 /*local */ );
314     if (code) {
315         UNLOCK_GLOBAL_MUTEX;
316         return code;
317     }
318
319     cell = cellname;
320
321     /* get an unauthenticated connection to desired cell */
322     code = ka_AuthServerConn(cell, KA_AUTHENTICATION_SERVICE, 0, &conn);
323     if (code) {
324         UNLOCK_GLOBAL_MUTEX;
325         return code;
326     }
327
328     code =
329         ka_Authenticate(name, instance, cell, conn,
330                         KA_TICKET_GRANTING_SERVICE, key, now,
331                         now + MAXKTCTICKETLIFETIME, &token, &pwexpires);
332     if (code) {
333         UNLOCK_GLOBAL_MUTEX;
334         return code;
335     }
336     code = ubik_ClientDestroy(conn);
337     UNLOCK_GLOBAL_MUTEX;
338     return code;
339 }