Imported Upstream version 1.15.1
[platform/upstream/krb5.git] / src / windows / leashdll / AFSroutines.c
1 //* Module name: AFSroutines.c
2
3 #include <windows.h>
4 #include <winsock2.h>
5 #include <stdio.h>
6 #include <time.h>
7
8 /* Private Include files */
9 #include <conf.h>
10 #include <leasherr.h>
11 #include "leashdll.h"
12 #include <leashwin.h>
13
14 #ifndef NO_AFS
15 #include <afs/stds.h>
16 #include <afs/auth.h>
17 #include <afs/krb.h>
18 #include <afs/cellconfig.h>
19 #endif
20 #include "leash-int.h"
21
22 #define MAXCELLCHARS   64
23 #define MAXHOSTCHARS   64
24 #define MAXHOSTSPERCELL 8
25 #define TRANSARCAFSDAEMON "TransarcAFSDaemon"
26 typedef struct {
27     char name[MAXCELLCHARS];
28     short numServers;
29     short flags;
30     struct sockaddr_in hostAddr[MAXHOSTSPERCELL];
31     char hostName[MAXHOSTSPERCELL][MAXHOSTCHARS];
32     char *linkedCell;
33 } afsconf_cell;
34
35 DWORD   AfsOnLine = 1;
36 extern  DWORD AfsAvailable;
37
38 int not_an_API_LeashAFSGetToken(TICKETINFO * ticketinfo, TicketList** ticketList, char * kprinc);
39 DWORD GetServiceStatus(LPSTR lpszMachineName, LPSTR lpszServiceName, DWORD *lpdwCurrentState);
40 BOOL SetAfsStatus(DWORD AfsStatus);
41 BOOL GetAfsStatus(DWORD *AfsStatus);
42 void Leash_afs_error(LONG rc, LPCSTR FailedFunctionName);
43
44 static char *afs_realm_of_cell(afsconf_cell *);
45 static long get_cellconfig_callback(void *, struct sockaddr_in *, char *);
46 static int get_cellconfig(char *, afsconf_cell *, char *);
47
48 /**************************************/
49 /* LeashAFSdestroyToken():            */
50 /**************************************/
51 int
52 Leash_afs_unlog(
53     void
54     )
55 {
56 #ifdef NO_AFS
57     return(0);
58 #else
59     long        rc;
60     char    HostName[64];
61     DWORD   CurrentState;
62
63     if (!AfsAvailable || GetAfsStatus(&AfsOnLine) && !AfsOnLine)
64         return(0);
65
66     CurrentState = 0;
67     memset(HostName, '\0', sizeof(HostName));
68     gethostname(HostName, sizeof(HostName));
69     if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
70         return(0);
71     if (CurrentState != SERVICE_RUNNING)
72         return(0);
73
74     rc = ktc_ForgetAllTokens();
75
76     return(0);
77 #endif
78 }
79
80
81 int
82 not_an_API_LeashAFSGetToken(
83     TICKETINFO * ticketinfo,
84     TicketList** ticketList,
85     char * kerberosPrincipal
86     )
87 {
88 #ifdef NO_AFS
89     return(0);
90 #else
91     struct ktc_principal    aserver;
92     struct ktc_principal    aclient;
93     struct ktc_token        atoken;
94     int                     EndMonth;
95     int                     EndDay;
96     int                     cellNum;
97     int                     BreakAtEnd;
98     char                    UserName[64];
99     char                    CellName[64];
100     char                    ServiceName[64];
101     char                    InstanceName[64];
102     char                    EndTime[16];
103     char                    Buffer[256];
104     char                    Months[12][4] = {"Jan\0", "Feb\0", "Mar\0", "Apr\0", "May\0", "Jun\0", "Jul\0", "Aug\0", "Sep\0", "Oct\0", "Nov\0", "Dec\0"};
105     char                    TokenStatus[16];
106     time_t                  CurrentTime;
107     struct tm               *newtime;
108     DWORD                   CurrentState;
109     DWORD                   rc;
110     char                    HostName[64];
111
112
113     TicketList* list = NULL;
114     if ( ticketinfo ) {
115         ticketinfo->btickets = NO_TICKETS;
116         ticketinfo->principal[0] = '\0';
117     }
118     if ( !kerberosPrincipal )
119         kerberosPrincipal = "";
120
121     if (!AfsAvailable || GetAfsStatus(&AfsOnLine) && !AfsOnLine)
122         return(0);
123
124     CurrentState = 0;
125     memset(HostName, '\0', sizeof(HostName));
126     gethostname(HostName, sizeof(HostName));
127     if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
128         return(0);
129     if (CurrentState != SERVICE_RUNNING)
130         return(0);
131
132     BreakAtEnd = 0;
133     cellNum = 0;
134     while (1)
135     {
136         if (rc = ktc_ListTokens(cellNum, &cellNum, &aserver))
137         {
138             if (rc != KTC_NOENT)
139                 return(0);
140
141             if (BreakAtEnd == 1)
142                 break;
143         }
144         BreakAtEnd = 1;
145         memset(&atoken, '\0', sizeof(atoken));
146         if (rc = ktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient))
147         {
148             if (rc == KTC_ERROR)
149                 return(0);
150
151             continue;
152         }
153
154         if (!list)
155         {
156             list = (TicketList*) calloc(1, sizeof(TicketList));
157             (*ticketList) = list;
158         }
159         else
160         {
161             list->next = (struct TicketList*) calloc(1, sizeof(TicketList));
162             list = (TicketList*) list->next;
163         }
164
165         CurrentTime = time(NULL);
166
167         newtime = localtime(&atoken.endTime);
168
169         memset(UserName, '\0', sizeof(UserName));
170         strcpy(UserName, aclient.name);
171
172         memset(CellName, '\0', sizeof(CellName));
173         strcpy(CellName, aclient.cell);
174
175         memset(InstanceName, '\0', sizeof(InstanceName));
176         strcpy(InstanceName, aclient.instance);
177
178         memset(ServiceName, '\0', sizeof(ServiceName));
179         strcpy(ServiceName, aserver.name);
180
181         memset(TokenStatus, '\0', sizeof(TokenStatus));
182
183         EndDay = newtime->tm_mday;
184
185         EndMonth = newtime->tm_mon + 1;;
186
187         sprintf(EndTime, "%02d:%02d:%02d", newtime->tm_hour, newtime->tm_min, newtime->tm_sec);
188
189         sprintf(Buffer,"                          %s %02d %s      %s%s%s@%s  %s",
190                 Months[EndMonth - 1], EndDay, EndTime,
191                 UserName,
192                 InstanceName[0] ? "." : "",
193                 InstanceName,
194                 CellName,
195                 TokenStatus);
196
197         list->theTicket = (char*) calloc(1, sizeof(Buffer));
198         if (!list->theTicket)
199         {
200 #ifdef USE_MESSAGE_BOX
201             MessageBox(NULL, "Memory Error", "Error", MB_OK);
202 #endif /* USE_MESSAGE_BOX */
203             return ENOMEM;
204         }
205
206         strcpy(list->theTicket, Buffer);
207         list->name = strdup(aclient.name);
208         list->inst = aclient.instance[0] ? strdup(aclient.instance) : NULL;
209         list->realm = strdup(aclient.cell);
210         list->encTypes = NULL;
211         list->addrCount = 0;
212         list->addrList = NULL;
213
214         if ( ticketinfo ) {
215             sprintf(Buffer,"%s@%s",UserName,CellName);
216             if (!ticketinfo->principal[0] || !stricmp(Buffer,kerberosPrincipal)) {
217                 strcpy(ticketinfo->principal, Buffer);
218                 ticketinfo->issue_date = 0;
219                 ticketinfo->lifetime = atoken.endTime;
220                 ticketinfo->renew_till = 0;
221
222                 _tzset();
223                 if ( ticketinfo->lifetime - time(0) <= 0L )
224                     ticketinfo->btickets = EXPD_TICKETS;
225                 else
226                     ticketinfo->btickets = GOOD_TICKETS;
227             }
228         }
229     }
230     return(0);
231 #endif
232 }
233
234 static char OpenAFSConfigKeyName[] = "SOFTWARE\\OpenAFS\\Client";
235
236 static int
237 use_krb524(void)
238 {
239     HKEY parmKey;
240     DWORD code, len;
241     DWORD use524 = 0;
242
243     code = RegOpenKeyEx(HKEY_CURRENT_USER, OpenAFSConfigKeyName,
244                          0, KEY_QUERY_VALUE, &parmKey);
245     if (code == ERROR_SUCCESS) {
246         len = sizeof(use524);
247         code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
248                                 (BYTE *) &use524, &len);
249         RegCloseKey(parmKey);
250     }
251     if (code != ERROR_SUCCESS) {
252         code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
253                              0, KEY_QUERY_VALUE, &parmKey);
254         if (code == ERROR_SUCCESS) {
255             len = sizeof(use524);
256             code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
257                                     (BYTE *) &use524, &len);
258             RegCloseKey (parmKey);
259         }
260     }
261     return use524;
262 }
263
264
265
266 int
267 Leash_afs_klog(
268     char *service,
269     char *cell,
270     char *realm,
271     int LifeTime
272     )
273 {
274 /////#ifdef NO_AFS
275 #if defined(NO_AFS) || defined(NO_KRB4)
276     return(0);
277 #else
278     long        rc;
279 ////This is defined in krb.h:
280     CREDENTIALS creds;
281     KTEXT_ST    ticket;
282     struct ktc_principal        aserver;
283     struct ktc_principal        aclient;
284     char        realm_of_user[REALM_SZ]; /* Kerberos realm of user */
285     char        realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
286     char        local_cell[MAXCELLCHARS+1];
287     char        Dmycell[MAXCELLCHARS+1];
288     struct ktc_token    atoken;
289     struct ktc_token    btoken;
290     afsconf_cell        ak_cellconfig; /* General information about the cell */
291     char        RealmName[128];
292     char        CellName[128];
293     char        ServiceName[128];
294     DWORD       CurrentState;
295     char        HostName[64];
296     BOOL        try_krb5 = 0;
297     int         retry = 0;
298     int         len;
299 #ifndef NO_KRB5
300     krb5_context  context = 0;
301     krb5_ccache  _krb425_ccache = 0;
302     krb5_creds increds;
303     krb5_creds * k5creds = 0;
304     krb5_error_code r;
305     krb5_principal client_principal = 0;
306     krb5_flags          flags = 0;
307 #endif /* NO_KRB5 */
308
309     if (!AfsAvailable || GetAfsStatus(&AfsOnLine) && !AfsOnLine)
310         return(0);
311
312     if ( !realm ) realm = "";
313     if ( !cell )  cell = "";
314     if ( !service ) service = "";
315
316     CurrentState = 0;
317     memset(HostName, '\0', sizeof(HostName));
318     gethostname(HostName, sizeof(HostName));
319     if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
320         return(0);
321     if (CurrentState != SERVICE_RUNNING)
322         return(0);
323
324     memset(RealmName, '\0', sizeof(RealmName));
325     memset(CellName, '\0', sizeof(CellName));
326     memset(ServiceName, '\0', sizeof(ServiceName));
327     memset(realm_of_user, '\0', sizeof(realm_of_user));
328     memset(realm_of_cell, '\0', sizeof(realm_of_cell));
329     memset(Dmycell, '\0', sizeof(Dmycell));
330
331     // NULL or empty cell returns information on local cell
332     if (cell && cell[0])
333         strcpy(Dmycell, cell);
334     rc = get_cellconfig(Dmycell, &ak_cellconfig, local_cell);
335     if (rc && cell && cell[0]) {
336         memset(Dmycell, '\0', sizeof(Dmycell));
337         rc = get_cellconfig(Dmycell, &ak_cellconfig, local_cell);
338     }
339     if (rc)
340         return(rc);
341
342 #ifndef NO_KRB5
343     if (!(r = Leash_krb5_initialize(&context, &_krb425_ccache))) {
344         int i;
345
346         memset((char *)&increds, 0, sizeof(increds));
347
348         (*pkrb5_cc_get_principal)(context, _krb425_ccache, &client_principal);
349         i = krb5_princ_realm(context, client_principal)->length;
350         if (i > REALM_SZ-1)
351             i = REALM_SZ-1;
352         strncpy(realm_of_user,krb5_princ_realm(context, client_principal)->data,i);
353         realm_of_user[i] = 0;
354         try_krb5 = 1;
355     }
356 #endif /* NO_KRB5 */
357
358 #ifndef NO_KRB4
359     if ( !try_krb5 || !realm_of_user[0] ) {
360         if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
361         {
362             return(rc);
363         }
364     }
365 #endif
366     strcpy(realm_of_cell, afs_realm_of_cell(&ak_cellconfig));
367
368     if (strlen(service) == 0)
369         strcpy(ServiceName, "afs");
370     else
371         strcpy(ServiceName, service);
372
373     if (strlen(cell) == 0)
374         strcpy(CellName, local_cell);
375     else
376         strcpy(CellName, cell);
377
378     if (strlen(realm) == 0)
379         strcpy(RealmName, realm_of_cell);
380     else
381         strcpy(RealmName, realm);
382
383     memset(&creds, '\0', sizeof(creds));
384
385 #ifndef NO_KRB5
386     if ( try_krb5 ) {
387         /* First try Service/Cell@REALM */
388         if (r = (*pkrb5_build_principal)(context, &increds.server,
389                                       strlen(RealmName),
390                                       RealmName,
391                                       ServiceName,
392                                       CellName,
393                                       0))
394         {
395             try_krb5 = 0;
396             goto use_krb4;
397         }
398
399         increds.client = client_principal;
400         increds.times.endtime = 0;
401         /* Ask for DES since that is what V4 understands */
402         increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
403
404 #ifdef KRB5_TC_NOTICKET
405         flags = 0;
406         r = pkrb5_cc_set_flags(context, _krb425_ccache, flags);
407 #endif
408         if (r == 0)
409             r = pkrb5_get_credentials(context, 0, _krb425_ccache, &increds, &k5creds);
410         if (r == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
411                         r == KRB5KRB_ERR_GENERIC /* Heimdal */) {
412             /* Next try Service@REALM */
413             pkrb5_free_principal(context, increds.server);
414             r = pkrb5_build_principal(context, &increds.server,
415                                       strlen(RealmName),
416                                       RealmName,
417                                       ServiceName,
418                                       0);
419             if (r == 0)
420                 r = pkrb5_get_credentials(context, 0, _krb425_ccache, &increds, &k5creds);
421         }
422
423         pkrb5_free_principal(context, increds.server);
424         pkrb5_free_principal(context, client_principal);
425 #ifdef KRB5_TC_NOTICKET
426         flags = KRB5_TC_NOTICKET;
427         pkrb5_cc_set_flags(context, _krb425_ccache, flags);
428 #endif
429         (void) pkrb5_cc_close(context, _krb425_ccache);
430         _krb425_ccache = 0;
431
432         if (r || k5creds == 0) {
433             pkrb5_free_context(context);
434             try_krb5 = 0;
435             goto use_krb4;
436         }
437
438         /* This code inserts the entire K5 ticket into the token
439          * No need to perform a krb524 translation which is
440          * commented out in the code below
441          */
442         if ( use_krb524() || k5creds->ticket.length > MAXKTCTICKETLEN )
443             goto try_krb524d;
444
445         memset(&aserver, '\0', sizeof(aserver));
446         strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
447         strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
448
449         memset(&atoken, '\0', sizeof(atoken));
450         atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
451         atoken.startTime = k5creds->times.starttime;
452         atoken.endTime = k5creds->times.endtime;
453         memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
454         atoken.ticketLen = k5creds->ticket.length;
455         memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
456
457       retry_gettoken5:
458         rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
459         if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
460             if ( rc == KTC_NOCM && retry < 20 ) {
461                 Sleep(500);
462                 retry++;
463                 goto retry_gettoken5;
464             }
465             goto try_krb524d;
466         }
467
468         if (atoken.kvno == btoken.kvno &&
469              atoken.ticketLen == btoken.ticketLen &&
470              !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
471              !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
472         {
473             /* Success */
474             pkrb5_free_creds(context, k5creds);
475             pkrb5_free_context(context);
476             return(0);
477         }
478
479         // * Reset the "aclient" structure before we call ktc_SetToken.
480         // * This structure was first set by the ktc_GetToken call when
481         // * we were comparing whether identical tokens already existed.
482
483         len = min(k5creds->client->data[0].length,MAXKTCNAMELEN - 1);
484         strncpy(aclient.name, k5creds->client->data[0].data, len);
485         aclient.name[len] = '\0';
486
487         if ( k5creds->client->length > 1 ) {
488             char * p;
489             strcat(aclient.name, ".");
490             p = aclient.name + strlen(aclient.name);
491             len = min(k5creds->client->data[1].length,MAXKTCNAMELEN - strlen(aclient.name) - 1);
492             strncpy(p, k5creds->client->data[1].data, len);
493             p[len] = '\0';
494         }
495         aclient.instance[0] = '\0';
496
497         strcpy(aclient.cell, realm_of_cell);
498
499         len = min(k5creds->client->realm.length,strlen(realm_of_cell));
500         if ( strncmp(realm_of_cell, k5creds->client->realm.data, len) ) {
501             char * p;
502             strcat(aclient.name, "@");
503             p = aclient.name + strlen(aclient.name);
504             len = min(k5creds->client->realm.length,MAXKTCNAMELEN - strlen(aclient.name) - 1);
505             strncpy(p, k5creds->client->realm.data, len);
506             p[len] = '\0';
507         }
508
509         rc = ktc_SetToken(&aserver, &atoken, &aclient, 0);
510         if (!rc) {
511             /* Success */
512             pkrb5_free_creds(context, k5creds);
513             pkrb5_free_context(context);
514             return(0);
515         }
516
517       try_krb524d:
518         /* This requires krb524d to be running with the KDC */
519         r = pkrb524_convert_creds_kdc(context, k5creds, &creds);
520         pkrb5_free_creds(context, k5creds);
521                 pkrb5_free_context(context);
522         if (r) {
523             try_krb5 = 0;
524             goto use_krb4;
525         }
526         rc = KSUCCESS;
527     } else
528 #endif /* NO_KRB5 */
529     {
530       use_krb4:
531         rc = KFAILURE;
532     }
533     if (rc != KSUCCESS)
534     {
535             return(rc);
536     }
537
538         memset(&aserver, '\0', sizeof(aserver));
539     strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
540     strncpy(aserver.cell, CellName, MAXKTCNAMELEN - 1);
541
542     memset(&atoken, '\0', sizeof(atoken));
543     atoken.kvno = creds.kvno;
544     atoken.startTime = creds.issue_date;
545     atoken.endTime = (*pkrb_life_to_time)(creds.issue_date,creds.lifetime);
546     memcpy(&atoken.sessionKey, creds.session, 8);
547     atoken.ticketLen = creds.ticket_st.length;
548     memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
549
550     if (!(rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient)) &&
551         atoken.kvno == btoken.kvno &&
552         atoken.ticketLen == btoken.ticketLen &&
553         !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
554         !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
555     {
556         return(0);
557     }
558
559     // * Reset the "aclient" structure before we call ktc_SetToken.
560     // * This structure was first set by the ktc_GetToken call when
561     // * we were comparing whether identical tokens already existed.
562
563     strncpy(aclient.name, creds.pname, MAXKTCNAMELEN - 1);
564     aclient.name[MAXKTCNAMELEN - 1] = '\0';
565     if (creds.pinst[0])
566     {
567         strncat(aclient.name, ".", MAXKTCNAMELEN - 1 - strlen(aclient.name));
568         aclient.name[MAXKTCNAMELEN - 1] = '\0';
569         strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1 - strlen(aclient.name));
570         aclient.name[MAXKTCNAMELEN - 1] = '\0';
571     }
572     strcpy(aclient.instance, "");
573
574     if ( strcmp(realm_of_cell, creds.realm) )
575     {
576         strncat(aclient.name, "@", MAXKTCNAMELEN - 1 - strlen(aclient.name));
577         aclient.name[MAXKTCNAMELEN - 1] = '\0';
578         strncat(aclient.name, creds.realm, MAXKTCNAMELEN - 1 - strlen(aclient.name));
579         aclient.name[MAXKTCNAMELEN - 1] = '\0';
580     }
581     aclient.name[MAXKTCNAMELEN-1] = '\0';
582
583     strcpy(aclient.cell, CellName);
584
585     // * NOTE: On WIN32, the order of SetToken params changed...
586     // * to   ktc_SetToken(&aserver, &aclient, &atoken, 0)
587     // * from ktc_SetToken(&aserver, &atoken, &aclient, 0) on Unix...
588     // * The afscompat ktc_SetToken provides the Unix order
589
590     if (rc = ktc_SetToken(&aserver, &atoken, &aclient, 0))
591     {
592         Leash_afs_error(rc, "ktc_SetToken()");
593         return(rc);
594     }
595
596     return(0);
597 #endif
598 }
599
600 /**************************************/
601 /* afs_realm_of_cell():               */
602 /**************************************/
603 static char *afs_realm_of_cell(afsconf_cell *cellconfig)
604 {
605 #ifdef NO_AFS
606     return(0);
607 #else
608     char krbhst[MAX_HSTNM]="";
609     static char krbrlm[REALM_SZ+1]="";
610 #ifndef NO_KRB5
611     krb5_context  ctx = 0;
612     char ** realmlist=NULL;
613     krb5_error_code r;
614 #endif /* NO_KRB5 */
615
616     if (!cellconfig)
617         return 0;
618
619 #ifndef NO_KRB5
620     if ( pkrb5_init_context ) {
621         r = pkrb5_init_context(&ctx);
622         if ( !r )
623             r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
624         if ( !r && realmlist && realmlist[0] ) {
625             strcpy(krbrlm, realmlist[0]);
626             pkrb5_free_host_realm(ctx, realmlist);
627         }
628         if (ctx)
629             pkrb5_free_context(ctx);
630     }
631 #endif /* NO_KRB5 */
632
633     if ( !krbrlm[0] )
634     {
635         char *s = krbrlm;
636         char *t = cellconfig->name;
637         int c;
638
639         while (c = *t++)
640         {
641             if (islower(c)) c=toupper(c);
642             *s++ = c;
643         }
644         *s++ = 0;
645     }
646     return(krbrlm);
647 #endif
648 }
649
650 /**************************************/
651 /* get_cellconfig():                  */
652 /**************************************/
653 static int get_cellconfig(char *cell, afsconf_cell *cellconfig, char *local_cell)
654 {
655 #ifdef NO_AFS
656     return(0);
657 #else
658     int rc;
659
660     local_cell[0] = (char)0;
661     memset(cellconfig, 0, sizeof(*cellconfig));
662
663     /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
664     if (rc = cm_GetRootCellName(local_cell))
665     {
666         return(rc);
667     }
668
669     if (strlen(cell) == 0)
670         strcpy(cell, local_cell);
671
672     /* WIN32: cm_SearchCellFile(cell, pcallback, pdata) */
673     strcpy(cellconfig->name, cell);
674
675     return cm_SearchCell(cell, get_cellconfig_callback, NULL, (void*)cellconfig);
676 #endif
677 }
678
679 /**************************************/
680 /* get_cellconfig_callback():          */
681 /**************************************/
682 static long get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep)
683 {
684 #ifdef NO_AFS
685     return(0);
686 #else
687     afsconf_cell *cc = (afsconf_cell *)cellconfig;
688
689     cc->hostAddr[cc->numServers] = *addrp;
690     strcpy(cc->hostName[cc->numServers], namep);
691     cc->numServers++;
692     return(0);
693 #endif
694 }
695
696
697 /**************************************/
698 /* Leash_afs_error():           */
699 /**************************************/
700 void
701 Leash_afs_error(LONG rc, LPCSTR FailedFunctionName)
702 {
703 #ifdef NO_AFS
704     return;
705 #else
706 #ifdef USE_MESSAGE_BOX
707     char message[256];
708     const char *errText;
709
710     // Using AFS defines as error messages for now, until Transarc
711     // gets back to me with "string" translations of each of these
712     // const. defines.
713     if (rc == KTC_ERROR)
714       errText = "KTC_ERROR";
715     else if (rc == KTC_TOOBIG)
716       errText = "KTC_TOOBIG";
717     else if (rc == KTC_INVAL)
718       errText = "KTC_INVAL";
719     else if (rc == KTC_NOENT)
720       errText = "KTC_NOENT";
721     else if (rc == KTC_PIOCTLFAIL)
722       errText = "KTC_PIOCTLFAIL";
723     else if (rc == KTC_NOPIOCTL)
724       errText = "KTC_NOPIOCTL";
725     else if (rc == KTC_NOCELL)
726       errText = "KTC_NOCELL";
727     else if (rc == KTC_NOCM)
728       errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!";
729     else
730       errText = "Unknown error!";
731
732     sprintf(message, "%s\n(%s failed)", errText, FailedFunctionName);
733     MessageBox(NULL, message, "AFS", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
734 #endif /* USE_MESSAGE_BOX */
735     return;
736
737 #endif
738 }
739
740 DWORD GetServiceStatus(
741     LPSTR lpszMachineName,
742     LPSTR lpszServiceName,
743     DWORD *lpdwCurrentState)
744 {
745 #ifdef NO_AFS
746     return(NOERROR);
747 #else
748     DWORD           hr               = NOERROR;
749     SC_HANDLE       schSCManager     = NULL;
750     SC_HANDLE       schService       = NULL;
751     DWORD           fdwDesiredAccess = 0;
752     SERVICE_STATUS  ssServiceStatus  = {0};
753     BOOL            fRet             = FALSE;
754
755     if ((pOpenSCManagerA == NULL) ||
756         (pOpenServiceA == NULL) ||
757         (pQueryServiceStatus == NULL) ||
758         (pCloseServiceHandle == NULL))
759         {
760         *lpdwCurrentState = SERVICE_RUNNING;
761         return(NOERROR);
762         }
763
764     *lpdwCurrentState = 0;
765
766     fdwDesiredAccess = GENERIC_READ;
767
768     schSCManager = (*pOpenSCManagerA)(lpszMachineName,
769                                  NULL,
770                                  fdwDesiredAccess);
771
772     if(schSCManager == NULL)
773     {
774         hr = GetLastError();
775         goto cleanup;
776     }
777
778     schService = (*pOpenServiceA)(schSCManager,
779                              lpszServiceName,
780                              fdwDesiredAccess);
781
782     if(schService == NULL)
783     {
784         hr = GetLastError();
785         goto cleanup;
786     }
787
788     fRet = (*pQueryServiceStatus)(schService,
789                               &ssServiceStatus);
790
791     if(fRet == FALSE)
792     {
793         hr = GetLastError();
794         goto cleanup;
795     }
796
797     *lpdwCurrentState = ssServiceStatus.dwCurrentState;
798
799 cleanup:
800
801     (*pCloseServiceHandle)(schService);
802     (*pCloseServiceHandle)(schSCManager);
803
804     return(hr);
805 #endif
806 }
807
808 BOOL
809 SetAfsStatus(
810     DWORD AfsStatus
811     )
812 {
813 #ifdef NO_AFS
814     return(TRUE);
815 #else
816     return write_registry_setting(LEASH_SETTINGS_REGISTRY_VALUE_AFS_STATUS,
817                                   REG_DWORD, &AfsStatus,
818                                   sizeof(AfsStatus)) ? FALSE : TRUE;
819 #endif
820 }
821
822 BOOL
823 GetAfsStatus(
824     DWORD *AfsStatus
825     )
826 {
827 #ifdef NO_AFS
828     return(TRUE);
829 #else
830     return read_registry_setting(LEASH_SETTINGS_REGISTRY_VALUE_AFS_STATUS,
831                                  AfsStatus, sizeof(DWORD)) ? FALSE : TRUE;
832 #endif
833 }