rxgen, kauth: Set but not used variables
[openafs.git] / src / kauth / authclient.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 a convenient interface to the AuthServer. */
11
12 #include <afsconfig.h>
13 #include <afs/param.h>
14
15 #ifdef IGNORE_SOME_GCC_WARNINGS
16 # pragma GCC diagnostic warning "-Wstrict-prototypes"
17 # pragma GCC diagnostic warning "-Wimplicit-function-declaration"
18 #endif
19
20 #define UBIK_LEGACY_CALLITER 1
21
22 #include <afs/stds.h>
23 #include <afs/pthread_glock.h>
24 #include <sys/types.h>
25 #ifdef AFS_NT40_ENV
26 #include <winsock2.h>
27 #else
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #endif
31 #ifdef HAVE_STDINT_H
32 # include <stdint.h>
33 #endif
34 #include <string.h>
35 #include <stdio.h>
36 #include <des.h>
37 #include <des_prototypes.h>
38 #include <rx/rxkad.h>
39 #include <afs/cellconfig.h>
40 #include <ubik.h>
41 #include <afs/auth.h>
42 #include <afs/afsutil.h>
43 #include "kauth.h"
44 #include "kautils.h"
45
46 #ifdef UKERNEL
47 #include "afs_usrops.h"
48 #endif
49
50 static struct afsconf_dir *conf = 0;
51 static struct afsconf_cell explicit_cell_server_list;
52 static struct afsconf_cell debug_cell_server_list;
53 static int explicit = 0;
54 static int debug = 0;
55
56 #ifdef ENCRYPTIONBLOCKSIZE
57 #undef ENCRYPTIONBLOCKSIZE
58 #endif
59 #define ENCRYPTIONBLOCKSIZE (sizeof(des_cblock))
60
61 /* Copy the specified list of servers into a specially know cell named
62    "explicit".  The cell can then be used to debug experimental servers. */
63
64 void
65 ka_ExplicitCell(char *cell, afs_uint32 serverList[])
66 {
67     int i;
68
69     LOCK_GLOBAL_MUTEX;
70     ka_ExpandCell(cell, explicit_cell_server_list.name, 0);
71     for (i = 0; i < MAXHOSTSPERCELL; i++)
72         if (serverList[i]) {
73             explicit_cell_server_list.numServers = i + 1;
74             explicit_cell_server_list.hostAddr[i].sin_family = AF_INET;
75             explicit_cell_server_list.hostAddr[i].sin_addr.s_addr =
76                 serverList[i];
77             explicit_cell_server_list.hostName[i][0] = 0;
78             explicit_cell_server_list.hostAddr[i].sin_port =
79                 htons(AFSCONF_KAUTHPORT);
80 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
81             explicit_cell_server_list.hostAddr[i].sin_len =
82                 sizeof(struct sockaddr_in);
83 #endif
84             explicit = 1;
85         } else
86             break;
87     UNLOCK_GLOBAL_MUTEX;
88 }
89
90 static int
91 myCellLookup(struct afsconf_dir *conf, char *cell, char *service,
92              struct afsconf_cell *cellinfo)
93 {
94     if (debug) {
95         *cellinfo = debug_cell_server_list;
96         return 0;
97     } else if (explicit
98                && (strcmp(cell, explicit_cell_server_list.name) == 0)) {
99         *cellinfo = explicit_cell_server_list;
100         return 0;
101     }
102     /* call the real one */
103     else
104         return afsconf_GetCellInfo(conf, cell, service, cellinfo);
105 }
106
107 afs_int32
108 ka_GetServers(char *cell, struct afsconf_cell * cellinfo)
109 {
110     afs_int32 code;
111     char cellname[MAXKTCREALMLEN];
112
113     LOCK_GLOBAL_MUTEX;
114     if (cell && !strlen(cell))
115         cell = 0;
116     else
117         cell = lcstring(cellname, cell, sizeof(cellname));
118
119     if (!conf) {
120 #ifdef UKERNEL
121         conf = afs_cdir;
122 #else /* UKERNEL */
123         conf = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
124 #endif /* UKERNEL */
125         if (!conf) {
126             UNLOCK_GLOBAL_MUTEX;
127             return KANOCELLS;
128         }
129     }
130     code = myCellLookup(conf, cell, AFSCONF_KAUTHSERVICE, cellinfo);
131     UNLOCK_GLOBAL_MUTEX;
132     return code;
133 }
134
135 afs_int32
136 ka_GetSecurity(int service, struct ktc_token * token,
137                struct rx_securityClass ** scP, int *siP)
138 {                               /* security class index */
139     LOCK_GLOBAL_MUTEX;
140     *scP = 0;
141     switch (service) {
142     case KA_AUTHENTICATION_SERVICE:
143     case KA_TICKET_GRANTING_SERVICE:
144       no_security:
145         *scP = rxnull_NewClientSecurityObject();
146         *siP = RX_SCINDEX_NULL;
147         break;
148     case KA_MAINTENANCE_SERVICE:
149         if (!token)
150             goto no_security;
151         *scP =
152             rxkad_NewClientSecurityObject(rxkad_crypt, &token->sessionKey,
153                                           token->kvno, token->ticketLen,
154                                           token->ticket);
155         *siP = RX_SCINDEX_KAD;
156         break;
157     default:
158         UNLOCK_GLOBAL_MUTEX;
159         return KABADARGUMENT;
160     }
161     if (*scP == 0) {
162         printf("Failed gettting security object\n");
163         UNLOCK_GLOBAL_MUTEX;
164         return KARXFAIL;
165     }
166     UNLOCK_GLOBAL_MUTEX;
167     return 0;
168 }
169
170 afs_int32
171 ka_SingleServerConn(char *cell, char *server,   /* name of server to contact */
172                     int service, struct ktc_token * token,
173                     struct ubik_client ** conn)
174 {
175     afs_int32 code;
176     struct rx_connection *serverconns[2];
177     struct rx_securityClass *sc;
178     int si;                     /* security class index */
179     struct afsconf_cell cellinfo;       /* for cell auth server list */
180     int i;
181     int match;
182     char sname[MAXHOSTCHARS];
183     int snamel;
184
185     LOCK_GLOBAL_MUTEX;
186     code = ka_GetServers(cell, &cellinfo);
187     if (code) {
188         UNLOCK_GLOBAL_MUTEX;
189         return code;
190     }
191
192     lcstring(sname, server, sizeof(sname));
193     snamel = strlen(sname);
194     match = -1;
195     for (i = 0; i < cellinfo.numServers; i++) {
196         if (strncmp(cellinfo.hostName[i], sname, snamel) == 0) {
197             if (match >= 0) {
198                 UNLOCK_GLOBAL_MUTEX;
199                 return KANOCELLS;
200             } else
201                 match = i;
202         }
203     }
204     if (match < 0) {
205         UNLOCK_GLOBAL_MUTEX;
206         return KANOCELLS;
207     }
208
209     code = rx_Init(0);
210     if (code) {
211         UNLOCK_GLOBAL_MUTEX;
212         return code;
213     }
214
215     code = ka_GetSecurity(service, token, &sc, &si);
216     if (code) {
217         UNLOCK_GLOBAL_MUTEX;
218         return code;
219     }
220 #ifdef AFS_PTHREAD_ENV
221     serverconns[0] =
222         rx_GetCachedConnection(cellinfo.hostAddr[match].sin_addr.s_addr,
223                                cellinfo.hostAddr[match].sin_port, service, sc,
224                                si);
225 #else
226     serverconns[0] =
227         rx_NewConnection(cellinfo.hostAddr[match].sin_addr.s_addr,
228                          cellinfo.hostAddr[match].sin_port, service, sc, si);
229 #endif
230     serverconns[1] = 0;         /* terminate list */
231
232     /* next, pass list of server rx_connections (in serverconns), and a place
233      * to put the returned client structure that we'll use in all of our rpc
234      * calls (via ubik_Call) */
235     *conn = 0;
236     code = ubik_ClientInit(serverconns, conn);
237     rxs_Release(sc);
238     UNLOCK_GLOBAL_MUTEX;
239     if (code)
240         return KAUBIKINIT;
241     return 0;
242 }
243
244 afs_int32
245 ka_AuthSpecificServersConn(int service, struct ktc_token * token,
246                            struct afsconf_cell * cellinfo,
247                            struct ubik_client ** conn)
248 {
249     afs_int32 code;
250     struct rx_connection *serverconns[MAXSERVERS];
251     struct rx_securityClass *sc;
252     int si;                     /* security class index */
253     int i;
254
255     LOCK_GLOBAL_MUTEX;
256     code = rx_Init(0);
257     if (code) {
258         UNLOCK_GLOBAL_MUTEX;
259         return code;
260     }
261
262     code = ka_GetSecurity(service, token, &sc, &si);
263     if (code) {
264         UNLOCK_GLOBAL_MUTEX;
265         return code;
266     }
267
268     for (i = 0; i < cellinfo->numServers; i++)
269 #ifdef AFS_PTHREAD_ENV
270         serverconns[i] =
271             rx_GetCachedConnection(cellinfo->hostAddr[i].sin_addr.s_addr,
272                                    cellinfo->hostAddr[i].sin_port, service,
273                                    sc, si);
274 #else
275         serverconns[i] =
276             rx_NewConnection(cellinfo->hostAddr[i].sin_addr.s_addr,
277                              cellinfo->hostAddr[i].sin_port, service, sc, si);
278 #endif
279     serverconns[cellinfo->numServers] = 0;      /* terminate list */
280
281     /* next, pass list of server rx_connections (in serverconns), and a place
282      * to put the returned client structure that we'll use in all of our rpc
283      * calls (via ubik_Call) */
284     *conn = 0;
285     code = ubik_ClientInit(serverconns, conn);
286     rxs_Release(sc);
287     UNLOCK_GLOBAL_MUTEX;
288     if (code)
289         return KAUBIKINIT;
290     return 0;
291 }
292
293 afs_int32
294 ka_AuthServerConn(char *cell, int service, struct ktc_token * token,
295                   struct ubik_client ** conn)
296 {
297     afs_int32 code;
298     struct rx_connection *serverconns[MAXSERVERS];
299     struct rx_securityClass *sc;
300     int si;                     /* security class index */
301     int i;
302     struct afsconf_cell cellinfo;       /* for cell auth server list */
303
304     LOCK_GLOBAL_MUTEX;
305     code = ka_GetServers(cell, &cellinfo);
306     if (code) {
307         UNLOCK_GLOBAL_MUTEX;
308         return code;
309     }
310
311     code = rx_Init(0);
312     if (code) {
313         UNLOCK_GLOBAL_MUTEX;
314         return code;
315     }
316
317     code = ka_GetSecurity(service, token, &sc, &si);
318     if (code) {
319         UNLOCK_GLOBAL_MUTEX;
320         return code;
321     }
322
323     for (i = 0; i < cellinfo.numServers; i++)
324 #ifdef AFS_PTHREAD_ENV
325         serverconns[i] =
326             rx_GetCachedConnection(cellinfo.hostAddr[i].sin_addr.s_addr,
327                                    cellinfo.hostAddr[i].sin_port, service, sc,
328                                    si);
329 #else
330         serverconns[i] =
331             rx_NewConnection(cellinfo.hostAddr[i].sin_addr.s_addr,
332                              cellinfo.hostAddr[i].sin_port, service, sc, si);
333 #endif
334     serverconns[cellinfo.numServers] = 0;       /* terminate list */
335
336     /* next, pass list of server rx_connections (in serverconns), and a place
337      * to put the returned client structure that we'll use in all of our rpc
338      * calls (via ubik_Call) */
339     *conn = 0;
340     code = ubik_ClientInit(serverconns, conn);
341     rxs_Release(sc);
342     UNLOCK_GLOBAL_MUTEX;
343     if (code)
344         return KAUBIKINIT;
345     return 0;
346 }
347
348 static afs_int32
349 CheckTicketAnswer(ka_BBS * oanswer, afs_int32 challenge,
350                   struct ktc_token *token, struct ktc_principal *caller,
351                   struct ktc_principal *server, char *label,
352                   afs_int32 * pwexpires)
353 {
354     struct ka_ticketAnswer *answer;
355     unsigned char tempc;
356
357     answer = (struct ka_ticketAnswer *)oanswer->SeqBody;
358
359     if (challenge != ntohl(answer->challenge))
360         return KABADPROTOCOL;
361     memcpy(&token->sessionKey, &answer->sessionKey,
362            sizeof(token->sessionKey));
363     token->startTime = ntohl(answer->startTime);
364     token->endTime = ntohl(answer->endTime);
365     token->kvno = (short)ntohl(answer->kvno);
366     token->ticketLen = ntohl(answer->ticketLen);
367
368     if (tkt_CheckTimes(token->startTime, token->endTime, time(0)) < 0)
369         return KABADPROTOCOL;
370     if ((token->ticketLen < MINKTCTICKETLEN)
371         || (token->ticketLen > MAXKTCTICKETLEN))
372         return KABADPROTOCOL;
373
374     {
375         char *strings = answer->name;
376         int len;
377 #undef chkstr
378 #define chkstr(field) \
379         len = strlen (strings); \
380         if (len > MAXKTCNAMELEN) return KABADPROTOCOL;\
381         if ((field) && strcmp (field, strings)) return KABADPROTOCOL;\
382         strings += len+1
383
384 #define chknostr() \
385         len = strlen(strings); \
386         if (len > MAXKTCNAMELEN) return KABADPROTOCOL; \
387         strings += len+1
388
389         if (caller) {
390             chkstr(caller->name);
391             chkstr(caller->instance);
392             chkstr(caller->cell);
393         } else {
394             chknostr();
395             chknostr();
396             chknostr();
397         }
398         if (server) {
399             chkstr(server->name);
400             chkstr(server->instance);
401         } else {
402             chknostr();
403             chknostr();
404         }
405
406         if (oanswer->SeqLen -
407             ((strings - oanswer->SeqBody) + token->ticketLen + KA_LABELSIZE)
408             >= (ENCRYPTIONBLOCKSIZE + 12)
409             )
410             return KABADPROTOCOL;
411
412         memcpy(token->ticket, strings, token->ticketLen);
413         strings += token->ticketLen;
414         if (memcmp(strings, label, KA_LABELSIZE) != 0)
415             return KABADPROTOCOL;
416
417         if (pwexpires) {
418             afs_int32 temp;
419             strings += KA_LABELSIZE;
420             temp = round_up_to_ebs((strings - oanswer->SeqBody));
421
422             if (oanswer->SeqLen > temp) {
423                 strings = oanswer->SeqBody + temp;
424                 memcpy(&temp, strings, sizeof(afs_int32));
425                 tempc = ntohl(temp) >> 24;
426                 /* don't forget this if you add any more fields!
427                  * strings += sizeof(afs_int32);
428                  */
429             } else {
430                 tempc = 255;
431             }
432             *pwexpires = tempc;
433         }
434
435     }
436     return 0;
437 }
438
439 /* call this instead of stub and we'll guarantee to find a host that's up.
440  * this doesn't handle UNOTSYNC very well, should use ubik_Call if you care
441  */
442 static afs_int32
443 kawrap_ubik_Call(int (*aproc) (), struct ubik_client *aclient,
444                  afs_int32 aflags, void *p1, void *p2, void *p3, void *p4,
445                  void *p5, void *p6, void *p7, void *p8)
446 {
447     afs_int32 code, lcode;
448     int count;
449     int pass;
450
451     /* First pass only checks servers known running. Second checks all.
452      * Once we've cycled through all the servers and still nothing, return
453      * error code from the last server tried.
454      */
455     for (pass = 0, aflags |= UPUBIKONLY; pass < 2;
456          pass++, aflags &= ~UPUBIKONLY) {
457         code = 0;
458         count = 0;
459         do {                    /* Cycle through the servers */
460             lcode = code;
461             code =
462                 ubik_CallIter(aproc, aclient, aflags, &count, (long) p1,
463                               (long) p2, (long) p3, (long) p4,
464                               (long) p5, (long) p6, (long) p7,
465                               (long) p8, 0, 0, 0, 0, 0, 0, 0, 0);
466         } while ((code == UNOQUORUM) || (code == UNOTSYNC)
467                  || (code == KALOCKED) || (code == -1));
468
469         if (code != UNOSERVERS)
470             break;
471     }
472
473     /* If cycled through all the servers, return the last error code */
474     if ((code == UNOSERVERS) && lcode) {
475         code = lcode;
476     }
477     return code;
478 }
479
480 /* This is the interface to the AuthServer RPC routine Authenticate.  It
481    formats the request packet, calls the encryption routine on the answer,
482    calls Authenticate, and decrypts the response.  The response is checked for
483    correctness and its contents are copied into the token. */
484
485 /* Errors:
486      KABADKEY = the key failed when converted to a key schedule.  Probably bad
487        parity.
488      KAUBIKCALL - the call to Ubik returned an error, probably a communication
489        failure such as timeout.
490      KABADPROTOCOL - the returned packet was in error.  Since a packet was
491        returned it can be presumed that the AuthServer correctly interpreted
492        the response.  This may indicate an inauthentic AuthServer.
493      <other> - errors generated by the server process are returned directly.
494  */
495
496 afs_int32
497 ka_Authenticate(char *name, char *instance, char *cell, struct ubik_client * conn,      /* Ubik connection to the AuthServer in
498                                                                                          * the desired cell */
499                 int service,    /* ticket granting or admin service */
500                 struct ktc_encryptionKey * key, Date start, Date end,   /* ticket lifetime */
501                 struct ktc_token * token, afs_int32 * pwexpires)
502 {                               /* days until it expires */
503     afs_int32 code;
504     des_key_schedule schedule;
505     Date request_time;
506     struct ka_gettgtRequest request;
507     struct ka_gettgtAnswer answer_old;
508     struct ka_ticketAnswer answer;
509     ka_CBS arequest;
510     ka_BBS oanswer;
511     char *req_label;
512     char *ans_label;
513     int version;
514
515     LOCK_GLOBAL_MUTEX;
516     if ((code = des_key_sched(ktc_to_cblock(key), schedule))) {
517         UNLOCK_GLOBAL_MUTEX;
518         return KABADKEY;
519     }
520
521     if (service == KA_MAINTENANCE_SERVICE) {
522         req_label = KA_GETADM_REQ_LABEL;
523         ans_label = KA_GETADM_ANS_LABEL;
524     } else if (service == KA_TICKET_GRANTING_SERVICE) {
525         req_label = KA_GETTGT_REQ_LABEL;
526         ans_label = KA_GETTGT_ANS_LABEL;
527     } else {
528         UNLOCK_GLOBAL_MUTEX;
529         return KABADARGUMENT;
530     }
531
532     request_time = time(0);
533     request.time = htonl(request_time);
534     memcpy(request.label, req_label, sizeof(request.label));
535     arequest.SeqLen = sizeof(request);
536     arequest.SeqBody = (char *)&request;
537     des_pcbc_encrypt(arequest.SeqBody, arequest.SeqBody, arequest.SeqLen,
538                      schedule, ktc_to_cblockptr(key), ENCRYPT);
539
540     oanswer.MaxSeqLen = sizeof(answer);
541     oanswer.SeqLen = 0;
542     oanswer.SeqBody = (char *)&answer;
543
544     version = 2;
545     code =
546         kawrap_ubik_Call(KAA_AuthenticateV2, conn, 0, name, instance,
547                          (void*)(uintptr_t)start, (void*)(uintptr_t)end, &arequest, &oanswer, 0, 0);
548     if (code == RXGEN_OPCODE) {
549         oanswer.MaxSeqLen = sizeof(answer);
550         oanswer.SeqBody = (char *)&answer;
551         version = 1;
552         code =
553             ubik_KAA_Authenticate(conn, 0, name, instance, start, end,
554                                   &arequest, &oanswer);
555         if (code == RXGEN_OPCODE) {
556             oanswer.MaxSeqLen = sizeof(answer_old);
557             oanswer.SeqBody = (char *)&answer_old;
558             version = 0;
559             code =
560                 ubik_KAA_Authenticate_old(conn, 0, name, instance,
561                                           start, end, &arequest, &oanswer);
562         }
563         if (code == RXGEN_OPCODE) {
564             code = KAOLDINTERFACE;
565         }
566     }
567     if (code) {
568         UNLOCK_GLOBAL_MUTEX;
569         if ((code >= KAMINERROR) && (code <= KAMAXERROR))
570             return code;
571         return KAUBIKCALL;
572     }
573     des_pcbc_encrypt(oanswer.SeqBody, oanswer.SeqBody, oanswer.SeqLen,
574                      schedule, ktc_to_cblockptr(key), DECRYPT);
575
576     switch (version) {
577     case 1:
578     case 2:
579         {
580             struct ktc_principal caller;
581             strcpy(caller.name, name);
582             strcpy(caller.instance, instance);
583             strcpy(caller.cell, "");
584             code =
585                 CheckTicketAnswer(&oanswer, request_time + 1, token, &caller,
586                                   0, ans_label, pwexpires);
587             if (code) {
588                 UNLOCK_GLOBAL_MUTEX;
589                 return code;
590             }
591         }
592         break;
593     case 0:
594         answer_old.time = ntohl(answer_old.time);
595         answer_old.ticket_len = ntohl(answer_old.ticket_len);
596         if ((answer_old.time != request_time + 1)
597             || (answer_old.ticket_len < MINKTCTICKETLEN)
598             || (answer_old.ticket_len > MAXKTCTICKETLEN)) {
599             UNLOCK_GLOBAL_MUTEX;
600             return KABADPROTOCOL;
601         }
602         {
603             char *label = ((char *)answer_old.ticket) + answer_old.ticket_len;
604
605             if (strncmp(label, ans_label, sizeof(answer_old.label))) {
606                 UNLOCK_GLOBAL_MUTEX;
607                 return KABADPROTOCOL;
608             }
609             token->startTime = start;
610             token->endTime = end;
611             token->kvno = ntohl(answer_old.kvno);
612             token->ticketLen = answer_old.ticket_len;
613             memcpy(token->ticket, answer_old.ticket, sizeof(token->ticket));
614             memcpy(&token->sessionKey, &answer_old.sessionkey,
615                    sizeof(struct ktc_encryptionKey));
616         }
617         break;
618     default:
619         UNLOCK_GLOBAL_MUTEX;
620         return KAINTERNALERROR;
621     }
622
623     UNLOCK_GLOBAL_MUTEX;
624     return 0;
625 }
626
627 afs_int32
628 ka_GetToken(char *name, char *instance, char *cell, char *cname, char *cinst, struct ubik_client * conn,        /* Ubik conn to cell's AuthServer */
629             Date start, Date end,       /* desired ticket lifetime */
630             struct ktc_token * auth_token, char *auth_domain,
631             struct ktc_token * token)
632 {
633     struct ka_getTicketTimes times;
634     struct ka_getTicketAnswer answer_old;
635     struct ka_ticketAnswer answer;
636     afs_int32 code;
637     ka_CBS aticket;
638     ka_CBS atimes;
639     ka_BBS oanswer;
640     char *strings;
641     int len;
642     des_key_schedule schedule;
643     int version;
644     afs_int32 pwexpires;
645
646     LOCK_GLOBAL_MUTEX;
647     aticket.SeqLen = auth_token->ticketLen;
648     aticket.SeqBody = auth_token->ticket;
649
650     code = des_key_sched(ktc_to_cblock(&auth_token->sessionKey), schedule);
651     if (code) {
652         UNLOCK_GLOBAL_MUTEX;
653         return KABADKEY;
654     }
655
656     times.start = htonl(start);
657     times.end = htonl(end);
658     des_ecb_encrypt(&times, &times, schedule, ENCRYPT);
659
660     atimes.SeqLen = sizeof(times);
661     atimes.SeqBody = (char *)&times;
662
663     oanswer.SeqLen = 0;
664     oanswer.MaxSeqLen = sizeof(answer);
665     oanswer.SeqBody = (char *)&answer;
666
667     version = 1;
668     code =
669         ubik_KAT_GetTicket(conn, 0, auth_token->kvno, auth_domain,
670                   &aticket, name, instance, &atimes, &oanswer);
671     if (code == RXGEN_OPCODE) {
672         oanswer.SeqLen = 0;     /* this may be set by first call */
673         oanswer.MaxSeqLen = sizeof(answer_old);
674         oanswer.SeqBody = (char *)&answer_old;
675         version = 0;
676         code =
677             ubik_KAT_GetTicket_old(conn, 0, auth_token->kvno,
678                       auth_domain, &aticket, name, instance, &atimes,
679                       &oanswer);
680         if (code == RXGEN_OPCODE) {
681             code = KAOLDINTERFACE;
682         }
683     }
684     if (code) {
685         UNLOCK_GLOBAL_MUTEX;
686         if ((code >= KAMINERROR) && (code <= KAMAXERROR))
687             return code;
688         return KAUBIKCALL;
689     }
690
691     des_pcbc_encrypt(oanswer.SeqBody, oanswer.SeqBody, oanswer.SeqLen,
692                      schedule, ktc_to_cblockptr(&auth_token->sessionKey), DECRYPT);
693
694     switch (version) {
695     case 1:
696         {
697             struct ktc_principal server;
698             strcpy(server.name, name);
699             strcpy(server.instance, instance);
700             code =
701                 CheckTicketAnswer(&oanswer, 0, token, 0, &server,
702                                   KA_GETTICKET_ANS_LABEL, &pwexpires);
703             if (code) {
704                 UNLOCK_GLOBAL_MUTEX;
705                 return code;
706             }
707         }
708         break;
709     case 0:
710         token->startTime = ntohl(answer_old.startTime);
711         token->endTime = ntohl(answer_old.endTime);
712         token->ticketLen = ntohl(answer_old.ticketLen);
713         token->kvno = ntohl(answer_old.kvno);
714         memcpy(&token->sessionKey, &answer_old.sessionKey,
715                sizeof(token->sessionKey));
716
717         if (tkt_CheckTimes(token->startTime, token->endTime, time(0)) < 0) {
718             UNLOCK_GLOBAL_MUTEX;
719             return KABADPROTOCOL;
720         }
721         if ((token->ticketLen < MINKTCTICKETLEN)
722             || (token->ticketLen > MAXKTCTICKETLEN)) {
723             UNLOCK_GLOBAL_MUTEX;
724             return KABADPROTOCOL;
725         }
726         strings = answer_old.name;
727         len = strlen(strings);  /* check client name */
728         if ((len < 1) || (len > MAXKTCNAMELEN)) {
729             UNLOCK_GLOBAL_MUTEX;
730             return KABADPROTOCOL;
731         }
732         strings += len + 1;     /* check client instance */
733         len = strlen(strings);
734         if ((len < 0) || (len > MAXKTCNAMELEN)) {
735             UNLOCK_GLOBAL_MUTEX;
736             return KABADPROTOCOL;
737         }
738         strings += len + 1;
739         len = strlen(strings);  /* check client cell */
740         if ((len < 0) || (len > MAXKTCNAMELEN)) {
741             UNLOCK_GLOBAL_MUTEX;
742             return KABADPROTOCOL;
743         }
744         strings += len + 1;
745         len = strlen(strings);  /* check server name */
746         if ((len < 1) || (len > MAXKTCNAMELEN) || strcmp(name, strings)) {
747             UNLOCK_GLOBAL_MUTEX;
748             return KABADPROTOCOL;
749         }
750         strings += len + 1;
751         len = strlen(strings);  /* check server instance */
752         if ((len < 0) || (len > MAXKTCNAMELEN) || strcmp(instance, strings)) {
753             UNLOCK_GLOBAL_MUTEX;
754             return KABADPROTOCOL;
755         }
756         strings += len + 1;
757
758         if ((strings - oanswer.SeqBody + token->ticketLen) - oanswer.SeqLen >=
759             ENCRYPTIONBLOCKSIZE) {
760             UNLOCK_GLOBAL_MUTEX;
761             return KABADPROTOCOL;
762         }
763         memcpy(token->ticket, strings, token->ticketLen);
764
765         break;
766     default:
767         UNLOCK_GLOBAL_MUTEX;
768         return KAINTERNALERROR;
769     }
770
771     UNLOCK_GLOBAL_MUTEX;
772     return 0;
773 }
774
775 afs_int32
776 ka_ChangePassword(char *name, char *instance, struct ubik_client * conn,        /* Ubik connection to the AuthServer in
777                                                                                  * the desired cell */
778                   struct ktc_encryptionKey * oldkey,
779                   struct ktc_encryptionKey * newkey)
780 {
781     afs_int32 code;
782
783     LOCK_GLOBAL_MUTEX;
784     code =
785         ubik_KAM_SetPassword(conn, UBIK_CALL_NEW, name, instance, 0, *(EncryptionKey *)newkey);
786     UNLOCK_GLOBAL_MUTEX;
787     return code;
788 }