venus: Remove dedebug
[openafs.git] / src / tsm41 / aix_aklog.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 #include <afsconfig.h>
11 #include <afs/param.h>
12 #include <afs/com_err.h>
13
14
15 #if defined(AFS_AIX51_ENV)
16 #include <sys/types.h>
17 #include <sys/param.h>
18 #include <stdio.h>
19 #include <locale.h>
20 #include <nl_types.h>
21 #include <pwd.h>
22 #include <netdb.h>
23 #include <sys/socket.h>
24 #include <sys/file.h>
25 #ifdef HAVE_SYS_PAG_H
26 #include <sys/pag.h>
27 #endif
28 #include <errno.h>
29 #include <usersec.h>
30 #include <syslog.h>
31
32 #include <krb5.h>
33
34 #include <afs/cellconfig.h>
35 #include <afs/dirpath.h>
36 #include <rx/rxkad.h>
37 #include <afs/auth.h>
38 #include <afs/ktc.h>
39 #include <afs/token.h>
40 #include <afs/ptserver.h>
41 #include "aix_auth_prototypes.h"
42
43 static int uidpag = 0;
44 static int localuid = 0;
45 struct afsconf_cell ak_cellconfig; /* General information about the cell */
46 static char linkedcell[MAXCELLCHARS+1];
47 static krb5_ccache  _krb425_ccache = NULL;
48
49 #define AFSKEY "afs"
50 #define AFSINST ""
51
52 #ifndef ANAME_SZ
53 #define ANAME_SZ 40
54 #endif /* ANAME_SZ */
55 #ifndef REALM_SZ
56 #define REALM_SZ 40
57 #endif /* REALM_SZ */
58 #ifndef SNAME_SZ
59 #define SNAME_SZ 40
60 #endif /* SNAME_SZ */
61 #ifndef INST_SZ
62 #define INST_SZ 40
63 #endif /* INST_SZ */
64
65 /*
66  * Why doesn't AFS provide these prototypes?
67  */
68
69 extern int pioctl(char *, afs_int32, struct ViceIoctl *, afs_int32);
70
71 /*
72  * Other prototypes
73  */
74
75 static krb5_error_code get_credv5(krb5_context context, char *, char *, char *,
76                                   char *, krb5_creds **);
77 static int get_user_realm(krb5_context, char *);
78
79 #if defined(HAVE_KRB5_PRINC_SIZE) || defined(krb5_princ_size)
80
81 #define get_princ_str(c, p, n) krb5_princ_component(c, p, n)->data
82 #define get_princ_len(c, p, n) krb5_princ_component(c, p, n)->length
83 #define second_comp(c, p) (krb5_princ_size(c, p) > 1)
84 #define realm_data(c, p) krb5_princ_realm(c, p)->data
85 #define realm_len(c, p) krb5_princ_realm(c, p)->length
86
87 #elif defined(HAVE_KRB5_PRINCIPAL_GET_COMP_STRING)
88
89 #define get_princ_str(c, p, n) krb5_principal_get_comp_string(c, p, n)
90 #define get_princ_len(c, p, n) strlen(krb5_principal_get_comp_string(c, p, n))
91 #define second_comp(c, p) (krb5_principal_get_comp_string(c, p, 1) != NULL)
92 #define realm_data(c, p) krb5_realm_data(krb5_principal_get_realm(c, p))
93 #define realm_len(c, p) krb5_realm_length(krb5_principal_get_realm(c, p))
94
95 #else
96 #error "Must have either krb5_princ_size or krb5_principal_get_comp_string"
97 #endif
98
99 #if defined(HAVE_KRB5_CREDS_KEYBLOCK)
100
101 #define get_cred_keydata(c) c->keyblock.contents
102 #define get_cred_keylen(c) c->keyblock.length
103 #define get_creds_enctype(c) c->keyblock.enctype
104
105 #elif defined(HAVE_KRB5_CREDS_SESSION)
106
107 #define get_cred_keydata(c) c->session.keyvalue.data
108 #define get_cred_keylen(c) c->session.keyvalue.length
109 #define get_creds_enctype(c) c->session.keytype
110
111 #else
112 #error "Must have either keyblock or session member of krb5_creds"
113 #endif
114
115 char *
116 afs_realm_of_cell(krb5_context context, struct afsconf_cell *cellconfig, int fallback)
117 {
118     static char krbrlm[REALM_SZ+1];
119     char **hrealms = 0;
120     krb5_error_code retval;
121
122     if (!cellconfig)
123         return 0;
124
125     if (fallback) {
126         char * p;
127         p = strchr(cellconfig->hostName[0], '.');
128         if (p++)
129             strcpy(krbrlm, p);
130         else
131             strcpy(krbrlm, cellconfig->name);
132         for (p=krbrlm; *p; p++) {
133             if (islower(*p))
134                 *p = toupper(*p);
135         }
136     } else {
137         if (retval = krb5_get_host_realm(context,
138                                          cellconfig->hostName[0], &hrealms))
139             return 0;
140         if(!hrealms[0]) return 0;
141         strcpy(krbrlm, hrealms[0]);
142
143         if (hrealms) krb5_free_host_realm(context, hrealms);
144     }
145     return krbrlm;
146 }
147
148 int
149 aklog_authenticate(char *userName, char *response, int *reenter, char **message)
150 {
151     char *reason, *pword, prompt[256];
152     struct passwd *pwd;
153     int code, unixauthneeded, password_expires = -1;
154     int status;
155     krb5_context context;
156
157     syslog(LOG_AUTH|LOG_DEBUG, "LAM aklog: uidpag %s localuid %s",
158                                uidpag ? "yes" : "no",
159                                localuid ? "yes" : "no");
160
161     krb5_init_context(&context);
162     *reenter = 0;
163     *message = (char *)0;
164
165     status = auth_to_cell(context, userName, NULL, NULL);
166
167     if (status) {
168         char *str = afs_error_message(status);
169         *message = malloc(1024);
170 #ifdef HAVE_KRB5_SVC_GET_MSG
171         if (strncmp(str, "unknown", strlen("unknown")) == 0) {
172             krb5_svc_get_msg(status,&str);
173             sprintf(*message, "Unable to obtain AFS tokens: %s.\n",
174                     str);
175             krb5_free_string(context, str);
176         } else
177 #endif
178             sprintf(*message, "Unable to obtain AFS tokens: %s.\n",
179                     str);
180         return AUTH_FAILURE; /* NOTFOUND? */
181     }
182     return AUTH_SUCCESS;
183 }
184
185 static krb5_error_code
186 get_credv5(krb5_context context, char *user,
187            char *name, char *inst, char *realm,
188            krb5_creds **creds)
189 {
190     krb5_creds increds;
191     krb5_error_code r;
192     static krb5_principal client_principal = 0;
193     char *str;
194
195     memset(&increds, 0, sizeof(increds));
196     /* instance may be ptr to a null string. Pass null then */
197     if ((r = krb5_build_principal(context, &increds.server,
198                                   strlen(realm), realm,
199                                   name,
200                                   (inst && strlen(inst)) ? inst : NULL,
201                                   NULL))) {
202         return r;
203     }
204     r = krb5_cc_default(context, &_krb425_ccache);
205     if (r) {
206         syslog(LOG_AUTH|LOG_ERR, "LAM aklog: krb5_cc_default returns %d", r);
207         return r;
208     }
209     r = krb5_cc_get_principal(context, _krb425_ccache, &client_principal);
210     if (r) {
211         syslog(LOG_AUTH|LOG_ERR, "LAM aklog: krb5_cc_get_principal returns %d", r);
212         return r;
213     }
214     increds.client = client_principal;
215     increds.times.endtime = 0;
216     /* Ask for DES since that is what V4 understands */
217     get_creds_enctype((&increds)) = ENCTYPE_DES_CBC_CRC;
218
219     r = krb5_get_credentials(context, 0, _krb425_ccache, &increds, creds);
220
221     return r;
222 }
223
224
225 static int
226 get_user_realm(krb5_context context, char *realm)
227 {
228     static krb5_principal client_principal = 0;
229     int i;
230
231     if (!_krb425_ccache)
232         krb5_cc_default(context, &_krb425_ccache);
233     if (!client_principal)
234         krb5_cc_get_principal(context, _krb425_ccache, &client_principal);
235
236     i = realm_len(context, client_principal);
237     if (i > REALM_SZ-1) i = REALM_SZ-1;
238     strncpy(realm,realm_data(context, client_principal), i);
239     realm[i] = 0;
240
241     return 0;
242 }
243
244 int
245 aklog_chpass(char *userName, char *oldPasswd, char *newPasswd, char **message)
246 {
247     return AUTH_SUCCESS;
248 }
249
250 int
251 aklog_passwdexpired(char *userName, char **message)
252 {
253     return AUTH_SUCCESS;
254 }
255
256 int
257 aklog_passwdrestrictions(char *userName, char *newPasswd, char *oldPasswd,
258                          char **message)
259 {
260     return AUTH_SUCCESS;
261 }
262
263 char *
264 aklog_getpasswd(char * userName)
265 {
266     errno = ENOSYS;
267     return NULL;
268 }
269
270 static void *
271 aklog_open(char *name, char *domain, int mode, char *options)
272 {
273     char *opt;
274
275     /* I can't find this documented anywhere, but it looks like the "options"
276      * string is NUL-delimited (so NULs replace commas in the configuration
277      * file), and the end of the list is marked by an extra NUL. */
278
279     for (opt = options; opt && *opt; opt += strlen(opt) + 1) {
280         if (strcasecmp(opt, "uidpag") == 0) {
281             uidpag = 1;
282         }
283         if (strcasecmp(opt, "localuid") == 0) {
284             localuid = 1;
285         }
286     }
287     return NULL;
288 }
289
290 static int
291 get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell, char *linkedcell)
292 {
293     int status = 0;
294     struct afsconf_dir *configdir;
295
296     memset(local_cell, 0, sizeof(local_cell));
297     memset(cellconfig, 0, sizeof(*cellconfig));
298
299     if (!(configdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH))) {
300         return AFSCONF_NODB;
301     }
302
303     if (afsconf_GetLocalCell(configdir, local_cell, MAXCELLCHARS)) {
304         return AFSCONF_FAILURE;
305     }
306
307     if ((cell == NULL) || (cell[0] == 0))
308         cell = local_cell;
309
310     linkedcell[0] = '\0';
311     if (afsconf_GetCellInfo(configdir, cell, NULL, cellconfig)) {
312         status = AFSCONF_NOTFOUND;
313     }
314     if (cellconfig->linkedCell)
315         strncpy(linkedcell,cellconfig->linkedCell,MAXCELLCHARS);
316
317     (void) afsconf_Close(configdir);
318
319     return(status);
320 }
321
322 /*
323  * Log to a cell.  If the cell has already been logged to, return without
324  * doing anything.  Otherwise, log to it and mark that it has been logged
325  * to.
326  */
327 static int
328 auth_to_cell(krb5_context context, char *user, char *cell, char *realm)
329 {
330     int status = 0;
331     char username[BUFSIZ];      /* To hold client username structure */
332     afs_int32 viceId;           /* AFS uid of user */
333
334     char name[ANAME_SZ];        /* Name of afs key */
335     char primary_instance[INST_SZ];     /* Instance of afs key */
336     char secondary_instance[INST_SZ];   /* Backup instance to try */
337     int try_secondary = 0;              /* Flag to indicate if we try second */
338     char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
339     char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
340     char local_cell[MAXCELLCHARS+1];
341     char cell_to_use[MAXCELLCHARS+1]; /* Cell to authenticate to */
342     static char confname[512] = { 0 };
343     krb5_creds *v5cred = NULL;
344     struct ktc_principal aserver;
345     int afssetpag = 0, uid = -1;
346     struct passwd *pwd = NULL;
347     struct ktc_setTokenData *token = NULL;
348     struct ktc_tokenUnion *rxkadToken = NULL;
349
350     memset(name, 0, sizeof(name));
351     memset(primary_instance, 0, sizeof(primary_instance));
352     memset(secondary_instance, 0, sizeof(secondary_instance));
353     memset(realm_of_user, 0, sizeof(realm_of_user));
354     memset(realm_of_cell, 0, sizeof(realm_of_cell));
355     syslog(LOG_AUTH|LOG_DEBUG, "LAM aklog starting: user %s uid %d", user, getuid());
356     if (confname[0] == '\0') {
357         strncpy(confname, AFSDIR_CLIENT_ETC_DIRPATH, sizeof(confname));
358         confname[sizeof(confname) - 2] = '\0';
359     }
360
361     /* NULL or empty cell returns information on local cell */
362     if ((status = get_cellconfig(cell, &ak_cellconfig,
363                                  local_cell, linkedcell))) {
364         syslog(LOG_AUTH|LOG_ERR, "LAM aklog: get_cellconfig returns %d", status);
365         return(status);
366     }
367
368     strncpy(cell_to_use, ak_cellconfig.name, MAXCELLCHARS);
369     cell_to_use[MAXCELLCHARS] = 0;
370
371     /*
372      * Find out which realm we're supposed to authenticate to.  If one
373      * is not included, use the kerberos realm found in the credentials
374      * cache.
375      */
376
377     if (realm && realm[0]) {
378         strcpy(realm_of_cell, realm);
379     }
380     else {
381         char *afs_realm = afs_realm_of_cell(context, &ak_cellconfig, FALSE);
382
383         if (!afs_realm) {
384             syslog(LOG_AUTH|LOG_ERR, "LAM aklog: afs_realm_of_cell returns %d", status);
385             return AFSCONF_FAILURE;
386         }
387
388         strcpy(realm_of_cell, afs_realm);
389     }
390
391     /* We use the afs.<cellname> convention here...
392      *
393      * Doug Engert's original code had principals of the form:
394      *
395      * "afsx/cell@realm"
396      *
397      * in the KDC, so the name wouldn't conflict with DFS.  Since we're
398      * not using DFS, I changed it just to look for the following
399      * principals:
400      *
401      * afs/<cell>@<realm>
402      * afs@<realm>
403      *
404      * Because people are transitioning from afs@realm to afs/cell,
405      * we configure things so that if the first one isn't found, we
406      * try the second one.  You can select which one you prefer with
407      * a configure option.
408      */
409
410     strcpy(name, AFSKEY);
411
412     if (1 || strcasecmp(cell_to_use, realm_of_cell) != 0) {
413         strncpy(primary_instance, cell_to_use, sizeof(primary_instance));
414         primary_instance[sizeof(primary_instance)-1] = '\0';
415         if (strcasecmp(cell_to_use, realm_of_cell) == 0) {
416             try_secondary = 1;
417             secondary_instance[0] = '\0';
418         }
419     } else {
420         primary_instance[0] = '\0';
421         try_secondary = 1;
422         strncpy(secondary_instance, cell_to_use,
423                 sizeof(secondary_instance));
424         secondary_instance[sizeof(secondary_instance)-1] = '\0';
425     }
426
427     token = token_buildTokenJar(ak_cellconfig.name);
428     if (!token) {
429         syslog(LOG_AUTH|LOG_ERR, "LAM aklog: token_buildTokenJar returns NULL");
430         return ENOMEM;
431     }
432
433     /*
434      * Extract the session key from the ticket file and hand-frob an
435      * afs style authenticator.
436      */
437
438     /*
439      * Try to obtain AFS tickets.  Because there are two valid service
440      * names, we will try both, but trying the more specific first.
441      *
442      *  afs/<cell>@<realm> i.e. allow for single name with "."
443      *  afs@<realm>
444      */
445
446     status = get_credv5(context, user, name, primary_instance, realm_of_cell,
447                         &v5cred);
448
449     if ((status == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
450          status == KRB5KRB_ERR_GENERIC) && !realm_of_cell[0]) {
451         char *afs_realm = afs_realm_of_cell(context, &ak_cellconfig, TRUE);
452
453         if (!afs_realm) {
454             syslog(LOG_AUTH|LOG_ERR, "LAM aklog: afs_realm_of_cell returns %d", status);
455             status = AFSCONF_FAILURE;
456             goto done;
457         }
458
459         strcpy(realm_of_cell, afs_realm);
460
461         if (strcasecmp(cell_to_use, realm_of_cell) == 0) {
462             try_secondary = 1;
463             secondary_instance[0] = '\0';
464         }
465
466         status = get_credv5(context, user, name, primary_instance,
467                             realm_of_cell, &v5cred);
468     }
469     if (status == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
470         status == KRB5KRB_ERR_GENERIC) {
471         if (try_secondary)
472             status = get_credv5(context, user, name, secondary_instance,
473                                 realm_of_cell, &v5cred);
474     }
475
476     if (status) {
477         syslog(LOG_AUTH|LOG_ERR, "LAM aklog: get_credv5 returns %d", status);
478         goto done;
479     }
480
481     strncpy(aserver.name, AFSKEY, MAXKTCNAMELEN - 1);
482     strncpy(aserver.instance, AFSINST, MAXKTCNAMELEN - 1);
483     strncpy(aserver.cell, cell_to_use, MAXKTCREALMLEN - 1);
484
485     /*
486      * The default is to use rxkad2b, which means we put in a full
487      * V5 ticket.  If the user specifies -524, we talk to the
488      * 524 ticket converter.
489      */
490
491     {
492         char *p;
493         int len;
494         struct ktc_token atoken;
495
496         len = min(get_princ_len(context, v5cred->client, 0),
497                   second_comp(context, v5cred->client) ?
498                   MAXKTCNAMELEN - 2 : MAXKTCNAMELEN - 1);
499         strncpy(username, get_princ_str(context, v5cred->client, 0), len);
500         username[len] = '\0';
501
502         if (second_comp(context, v5cred->client)) {
503             strcat(username, ".");
504             p = username + strlen(username);
505             len = min(get_princ_len(context, v5cred->client, 1),
506                       MAXKTCNAMELEN - strlen(username) - 1);
507             strncpy(p, get_princ_str(context, v5cred->client, 1), len);
508             p[len] = '\0';
509         }
510
511         memset(&atoken, 0, sizeof(atoken));
512         atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
513         atoken.startTime = v5cred->times.starttime;;
514         atoken.endTime = v5cred->times.endtime;
515         memcpy(&atoken.sessionKey, get_cred_keydata(v5cred),
516                get_cred_keylen(v5cred));
517         atoken.ticketLen = v5cred->ticket.length;
518         memcpy(atoken.ticket, v5cred->ticket.data, atoken.ticketLen);
519
520         status = token_importRxkadViceId(&rxkadToken, &atoken, 0);
521         if (status) {
522             syslog(LOG_AUTH|LOG_ERR, "LAM aklog: importRxkad failed with %d", status);
523             goto done;
524         }
525     }
526
527     status = token_addToken(token, rxkadToken);
528     if (status) {
529         syslog(LOG_AUTH|LOG_ERR, "LAM aklog: addToken failed with %d", status);
530         goto done;
531     }
532
533     if ((status = get_user_realm(context, realm_of_user))) {
534         syslog(LOG_AUTH|LOG_ERR, "LAM aklog: get_user_realm returns %d", status);
535         status = KRB5_REALM_UNKNOWN;
536         goto done;
537     }
538     if (strcmp(realm_of_user, realm_of_cell)) {
539         strcat(username, "@");
540         strcat(username, realm_of_user);
541     }
542
543     uid = getuid();
544     if (uid == 0) {
545         pwd = getpwnam(user);
546         if (!pwd) {
547             syslog(LOG_AUTH|LOG_ERR, "LAM aklog: getpwnam %s failed", user);
548             status = AUTH_FAILURE;
549             goto done;
550         }
551     }
552
553     viceId = ANONYMOUSID;
554
555     if (!localuid) {
556         /* This actually crashes long-running daemons */
557         if (!pr_Initialize (0, confname, aserver.cell))
558             status = pr_SNameToId (username, &viceId);
559         if (status)
560             viceId = ANONYMOUSID;
561     } else {
562         /*
563          * This actually only works assuming that your uid and pts space match
564          * and probably this works only for the local cell anyway.
565          */
566
567         if (uid == 0) {
568             viceId = pwd->pw_uid;
569         } else {
570             viceId = uid;
571         }
572     }
573
574     /* Don't do first-time registration. Handle only the simple case */
575     if ((status == 0) && (viceId != ANONYMOUSID)) {
576         status = token_setRxkadViceId(rxkadToken, viceId);
577         if (status) {
578             syslog(LOG_AUTH|LOG_ERR, "LAM aklog: Error %d setting rxkad ViceId", status);
579             status = 0;
580         } else {
581             token_replaceToken(token, &rxkadToken);
582             syslog(LOG_AUTH|LOG_DEBUG, "LAM aklog: setting tokens for ViceId %d\n",
583                    (int)viceId);
584         }
585     }
586
587 #ifndef AFS_AIX51_ENV
588     /* on AIX 4.1.4 with AFS 3.4a+ if a write is not done before
589      * this routine, it will not add the token. It is not clear what
590      * is going on here! So we will do the following operation.
591      * On AIX 5 this kills our parent. So we won't.
592      */
593     write(2,"",0); /* dummy write */
594 #endif
595
596     /* If uidpag is set, we want to use UID-based PAGs, and not real PAGs, so
597      * don't create a new PAG if we're not in a PAG. But if uidpag is _not_
598      * set, just always create a new PAG. */
599     if (uidpag) {
600         afssetpag = (getpagvalue("afs") > 0) ? 1 : 0;
601         if (afssetpag) {
602             /* we can't set a UID PAG if we're already in a real PAG. Whine */
603             syslog(LOG_AUTH|LOG_ERR, "LAM aklog: uidpag is set, but we are "
604                                      "already in a PAG; this cannot work! "
605                                      "Attempting to continue by creating a "
606                                      "a new PAG");
607         }
608     } else {
609         afssetpag = 1;
610     }
611     token_setPag(token, afssetpag);
612
613     if (uid == 0 && uidpag) {
614         /* We are root, and we want to use UID-based PAGs. So, fork a child
615          * and setuid before setting tokens, so we set the tokens for the
616          * target user. */
617         struct sigaction newAction, origAction;
618         pid_t cid, pcid;
619         int wstatus;
620
621         sigemptyset(&newAction.sa_mask);
622         newAction.sa_handler = SIG_DFL;
623         newAction.sa_flags = 0;
624         status = sigaction(SIGCHLD, &newAction, &origAction);
625         if (status) {
626             syslog(LOG_AUTH|LOG_ERR, "LAM aklog: sigaction returned %d", status);
627             status = AUTH_FAILURE;
628             goto done;
629         }
630         syslog(LOG_AUTH|LOG_DEBUG, "LAM aklog: in daemon? forking to set tokens");
631         cid = fork();
632         if (cid <= 0) {
633             syslog(LOG_AUTH|LOG_DEBUG, "LAM aklog child: setting tokens");
634             setuid(pwd->pw_uid);
635             status = ktc_SetTokenEx(token);
636             if (status != 0)
637                 syslog(LOG_AUTH|LOG_ERR, "LAM aklog child: set tokens, returning %d", status);
638             exit((status == 0)?0:255);
639         } else {
640             do {
641                 pcid = waitpid(cid, &wstatus, 0);
642             } while ((pcid == -1) && (errno == EINTR));
643             if ((pcid == cid) && WIFEXITED(wstatus))
644                 status = WEXITSTATUS(wstatus);
645             else
646                 status = -1;
647         }
648         syslog(LOG_AUTH|LOG_DEBUG, "LAM aklog: collected child status %d", status);
649         sigaction(SIGCHLD, &origAction, NULL);
650     } else {
651         status = ktc_SetTokenEx(token);
652     }
653     if (status != 0)
654         syslog(LOG_AUTH|LOG_ERR, "LAM aklog: set tokens returned %d", status);
655     else
656         syslog(LOG_AUTH|LOG_DEBUG, "LAM aklog: set tokens, pag %d", getpagvalue("afs"));
657
658  done:
659     if (rxkadToken) {
660         token_freeToken(&rxkadToken);
661     }
662     token_FreeSet(&token);
663     return(status);
664 }
665
666 int
667 aklog_initialize(struct secmethod_table *meths)
668 {
669     memset(meths, 0, sizeof(struct secmethod_table));
670     syslog(LOG_AUTH|LOG_DEBUG, "LAM aklog loaded: uid %d pag %d", getuid(), getpagvalue("afs"));
671     /*
672      * Initialize the exported interface routines.
673      * Aside from method_authenticate and method_open, these are just no-ops.
674      */
675     meths->method_chpass = aklog_chpass;
676     meths->method_authenticate = aklog_authenticate;
677     meths->method_passwdexpired = aklog_passwdexpired;
678     meths->method_passwdrestrictions = aklog_passwdrestrictions;
679     meths->method_getpasswd = aklog_getpasswd;
680     meths->method_open = aklog_open;
681
682     return (0);
683 }
684 #endif /* AFS_AIX51_ENV */