add ignore_uid (like ignore_root) plus set_token (set token in auth step instead of setcred), refresh_token (no new pag), use_klog (fork a klog child), no_unlog, remainlifetime (sleep before deleting creds at logout)
<P>The recommended AFS-related entries in the PAM configuration file make use
of one or more of the following three attributes.
<DL>
+<h4><br>Authentication Management</h4>
<P><DT><B><TT>try_first_pass</TT>
</B><DD>This is a standard PAM attribute that can be included on entries after the
first one for a service; it directs the module to use the password that
the user's correct AFS password. For further discussion of this
attribute and its alternatives, see the operating system's PAM
documentation.
+<P>
<P><DT><B><TT>ignore_root</TT>
</B><DD>This attribute, specific to the AFS PAM module, directs it to ignore not
only the local superuser <B> root</B>, but also any user with UID 0
(zero).
+<P><DT><B><TT>ignore_uid <i>uid</i></TT>
+</B><DD>This option is an extension of the "ignore_root" switch. The additional
+parameter is a limit. Users with a uid up to the given parameter are ignored
+by <i>pam_afs.so</i>. Thus, a system administrator still has the opportunity to
+add local user accounts to his system by choosing between "low" and
+"high" user ids.<br>
+An example /etc/passwd file for "ignore_uid 100" may have entries like these:
+<PRE>
+ .
+ .
+afsuserone:x:99:100::/afs/afscell/u/afsuserone:/bin/bash
+afsusertwo:x:100:100::/afs/afscell/u/afsusertwo:/bin/bash
+localuserone:x:101:100::/home/localuserone:/bin/bash
+localusertwo:x:102:100::/home/localusertwo:/bin/bash
+ .
+ .
+</PRE><br>
+AFS accounts should be locked in the file /etc/shadow like this:
+<PRE>
+ .
+ .
+afsuserone:!!:11500:0:99999:7:::
+afsusertwo:!!:11500:0:99999:7:::
+localuserone:<thelocaluserone'skey>:11500:0:99999:7:::
+localusertwo:<thelocalusertwo'skey>:11500:0:99999:7:::
+ .
+ .
+</PRE><br>
+There is no need to store a local key in this file since the AFS
+password is sent and verfied at the AFS cell server!
+
<P><DT><B><TT>setenv_password_expires</TT>
</B><DD>This attribute, specific to the AFS PAM module, sets the environment
variable PASSWORD_EXPIRES to the expiration date of the user's AFS
password, which is recorded in the Authentication Database.
+<P><DT><B><TT>set_token</TT>
+</B><DD>Some applications don't call <i>pam_setcred()</i> in order to retrieve the appropriate
+credentials (here the AFS token) for their session. This switch sets the credentials
+already in <i>pam_sm_authenticate()</i> obsoleting a call to <i>pam_setcred()</i>.<br>
+<b>Caution: Don't use this switch for applications which do call <i>pam_setcred()</i>!</b>
+One example for an application not calling <i>pam_setcred()</i> are older versions of
+the samba server.<br>
+Nevertheless, using applications with working pam session management is recommended as this
+setup conforms better with the PAM definitions.
+<P><DT><B><TT>refresh_token</TT>
+</B><DD>This options is identical to "set_token" except that no new PAG is generated.
+This is necessary to handle processes like xlock or xscreensaver. It is not enough to give
+the screen and the keyboard free for the user who reactivated his screen typing in the
+correct AFS password, but one may also need fresh tokens with full
+livetime in order to work on, and the new token must be refreshed in the already existing PAG
+for the processes that have been started. This is achieved using this option.
+<P><DT><B><TT>use_klog</TT>
+</B><DD>Activating this switch the authentication is done by calling the external program "klog".
+One program requiring this is for example <i>kdm</i> of KDE 2.x.<br></DD>
+<P><DT><B><TT>dont_fork</TT>
+</B><DD>Usually, the password verification and the establishment of the token is performed
+in a sub process. Using this option pam_afs does not fork and performs all actions in a single
+process. <b>Only use this options in case you notice serious problems caused by the sub process.</b>
+This option has been developed in respect to the "mod_auth_pam"-project (see also
+<A HREF="http://pam.sourceforge.net/mod_auth_pam/">mod_auth_pam</A>). The mod_auth_pam
+module enables PAM authentication for the apache http server package.
+
+<h4><br>Session Management</h4>
+
+<P><DT><B><TT>no_unlog</TT>
+</B><DD>Normally the tokens are deleted (in memory) after the session ends. Using this options the tokens are left
+untouched. <b>This behaviour has been the default in pam_afs until openafs-1.1.1!</b>
+<P><DT><B><TT>remainlifetime <i>sec</i></TT>
+</B><DD>The tokens are kept active for <i>sec</i> seconds before they are deleted. X display managers
+i.e. are used to inform the applications started in the X session before the logout and then
+end themselves. If the token was deleted immediately the applications would have no chance to
+write back their settings to i.e. the user's AFS home space. This option may help to avoid the
+problem.<br>
+
</DL>
<P>Perform the following steps to enable AFS login.
<OL TYPE=1>
<P><LI>Mount the AFS CD-ROM for Linux on the <B>/cdrom</B> directory, if it
is not already. Then change to the directory for PAM modules, which
-depends on which Linux distribution you are using.
+depends on which Linux distribution you are using.
<P>If you are using a Linux distribution from Red Hat Software:
-<PRE>
- # <B>cd /lib/security</B>
-</PRE>
+<PRE>
+ # <B>cd /lib/security</B>
+</PRE>
<P>If you are using another Linux distribution:
-<PRE>
+<PRE>
# <B>cd /usr/lib/security</B>
-
+
</PRE>
<P><LI>Copy the appropriate AFS authentication library file to the directory to
which you changed in the previous step. Create a symbolic link whose
name does not mention the version. Omitting the version eliminates the
need to edit the PAM configuration file if you later update the library
-file.
+file.
<P>If you use the AFS Authentication Server (<B>kaserver</B>
process):
-<PRE>
+<PRE>
# <B>cp /cdrom/i386_linux22/lib/pam_afs.so.1 .</B>
-
- # <B>ln -s pam_afs.so.1 pam_afs.so</B>
-</PRE>
+
+ # <B>ln -s pam_afs.so.1 pam_afs.so</B>
+</PRE>
<P>If you use a Kerberos implementation of AFS authentication:
-<PRE>
+<PRE>
# <B>cp /cdrom/i386_linux22/lib/pam_afs.krb.so.1 .</B>
-
+
# <B>ln -s pam_afs.krb.so.1 pam_afs.so</B>
-
+
</PRE>
<P><LI>For each service with which you want to use AFS authentication, insert an
entry for the AFS PAM module into the <TT>auth</TT> section of the
service's PAM configuration file. (Linux uses a separate
configuration file for each service, unlike some other operating systems which
list all services in a single file.) Mark the entry as
-<TT>sufficient</TT> in the second field.
+<TT>sufficient</TT> in the second field.
<P>Place the AFS entry below any entries that impose conditions under which
you want the service to fail for a user who does not meet the entry's
requirements. Mark these entries <TT>required</TT>. Place the
AFS entry above any entries that need to execute only if AFS authentication
-fails.
+fails.
<P>Insert the following AFS entry if using the Red Hat distribution:
-<PRE>
- auth sufficient /lib/security/pam_afs.so try_first_pass ignore_root
-</PRE>
+<PRE>
+ auth sufficient /lib/security/pam_afs.so try_first_pass ignore_root
+</PRE>
<P>Insert the following AFS entry if using another distribution:
-<PRE>
- auth sufficient /usr/lib/security/pam_afs.so try_first_pass ignore_root
-</PRE>
-<P>The following example illustrates the recommended configuration of the
-configuration file for the <B>login</B> service
-(<B>/etc/pam.d/login</B>) on a machine using the Red Hat
-distribution.
-<PRE>
+<PRE>
+ auth sufficient /usr/lib/security/pam_afs.so try_first_pass ignore_root
+</PRE>
+<P>Check the PAM config files also for "session" entries. If there are
+lines beginning with "session" then please insert this line too:
+<PRE>
+ session optional /lib/security/pam_afs.so
+</PRE>
+<P>or
+<PRE>
+ session optional /usr/lib/security/pam_afs.so
+</PRE>
+<P>This guaranties that the user's tokens are deleted from memory after his
+session ends so that no other user coincidently gets those tokens without authorization!
+The following examples illustrate the recommended configuration of the
+configuration file for several services:<br>
+
+<h4><br>Authentication Management</h4>
+
+(<B>/etc/pam.d/login</B>)
+<PRE>
#%PAM-1.0
auth required /lib/security/pam_securetty.so
auth required /lib/security/pam_nologin.so
auth sufficient /lib/security/pam_afs.so try_first_pass ignore_root
+ # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ #This enables AFS authentication for every user but root
auth required /lib/security/pam_pwdb.so shadow nullok
account required /lib/security/pam_pwdb.so
password required /lib/security/pam_cracklib.so
password required /lib/security/pam_pwdb.so shadow nullok use_authtok
+ session optional /lib/security/pam_afs.so
+ #Make sure tokens are deleted after the user logs out
session required /lib/security/pam_pwdb.so
-
-</PRE>
+
+</PRE><br>
+(<b>/etc/pam.d/samba</b>)
+<PRE>
+ auth required /lib/security/pam_afs.so ignore_uid 100 set_token
+ # ^^^^^^^^^^^^^^^^^^^^^^^^
+ #Here, users with uid>100 are considered to belong to the AFS and users
+ #with uid<=100 are ignored by pam_afs. The token is retrieved already in
+ #pam_sm_authenticate() (this is an example pam config for a samba version
+ #that does not call pam_setcred(), it also does no sense to include session
+ #entries here since they would be ignored by this version of samba ).
+ account required /lib/security/pam_pwdb.so
+</PRE>
+(<b>/etc/pam.d/xscreensaver</b>)
+<PRE>
+ auth sufficient /lib/security/pam_afs.so ignore_uid 100 refresh_token
+ # ^^^^^^^^^^^^^
+ #Avoid generating a new PAG for the new tokens, use the already existing PAG and
+ #establish a fresh token in it.
+ auth required /lib/security/pam_pwdb.so try_first_pass
+</PRE>
+(<b>/etc/pam.d/httpd</b>)
+<PRE>
+ auth required /lib/security/pam_afs.so ignore_uid 100 dont_fork
+ # ^^^^^^^^^
+ #Don't fork for the verification of the password.
+</PRE>
+
+<h4><br>Session Management</h4>
+
+(<b>/etc/pam.d/su</b>)
+<PRE>
+ auth sufficient /lib/security/pam_afs.so ignore_uid 100
+ auth required /lib/security/pam_pwdb.so try_first_pass
+ account required /lib/security/pam_pwdb.so
+ password required /lib/security/pam_cracklib.so
+ password required /lib/security/pam_pwdb.so use_authtok
+ session required /lib/security/pam_pwdb.so
+ session optional /lib/security/pam_afs.so no_unlog
+ # ^^^^^^^^
+ #Don't delete the token in this case, since the user may still
+ #need it (for example if somebody logs in and changes to root
+ #afterwards he may still want to access his home space in AFS).
+ session required /lib/security/pam_login_access.so
+ session optional /lib/security/pam_xauth.so
+</PRE>
+(<b>/etc/pam.d/xdm</b>)
+<PRE>
+ auth required /lib/security/pam_nologin.so
+ auth required /lib/security/pam_login_access.so
+ auth sufficient /lib/security/pam_afs.so ignore_uid 100 use_klog
+ auth required /lib/security/pam_pwdb.so try_first_pass
+ account required /lib/security/pam_pwdb.so
+ password required /lib/security/pam_cracklib.so
+ password required /lib/security/pam_pwdb.so shadow nullok use_authtok
+ session optional /lib/security/pam_afs.so remainlifetime 10
+ # ^^^^^^^^^^^^^^^^^
+ #Wait 10 seconds before deleting the AFS tokens in order to give
+ #the programs of the X session some time to save their settings
+ #to AFS.
+ session required /lib/security/pam_pwdb.so
+</PRE>
+
<P><LI>Proceed to <A HREF="#HDRWQ145">Loading and Creating Client Files</A>.
</OL>
<A NAME="IDX2986"></A>
#define RET(x) { retcode = (x); goto out; }
-
extern int
pam_sm_authenticate(
pam_handle_t *pamh,
int nowarn = 0;
int use_first_pass = 0;
int try_first_pass = 0;
- int ignore_root = 0;
- int trust_root = 0;
- int catch_su = 0;
+ int ignore_uid = 0;
+ uid_t ignore_uid_id = 0;
+ char my_password_buf[256];
+ /*
+ * these options are added to handle stupid apps, which won't call
+ * pam_set_cred()
+ */
+ int refresh_token = 0;
+ int set_token = 0;
+ int dont_fork = 0;
+ /* satisfy kdm 2.x
+ */
+ int use_klog = 0;
int set_expires = 0; /* This option is only used in pam_set_cred() */
int got_authtok = 0; /* got PAM_AUTHTOK upon entry */
int nouser = 0;
- char my_password_buf[256];
char *user = NULL, *password = NULL;
+ long password_expires = -1;
int torch_password = 1;
int i;
struct pam_conv *pam_convp = NULL;
#ifndef AFS_SUN56_ENV
- openlog(pam_afs_ident, LOG_CONS, LOG_AUTH);
+ openlog(pam_afs_ident, LOG_CONS|LOG_PID, LOG_AUTH);
#endif
origmask = setlogmask(logmask);
} else if (strcasecmp(argv[i], "try_first_pass") == 0) {
try_first_pass = 1;
} else if (strcasecmp(argv[i], "ignore_root" ) == 0) {
- ignore_root = 1;
- } else if (strcasecmp(argv[i], "trust_root" ) == 0) {
- trust_root = 1;
- } else if (strcasecmp(argv[i], "catch_su" ) == 0) {
- catch_su = 1;
+ ignore_uid = 1;
+ ignore_uid_id = 0;
+ } else if (strcasecmp(argv[i], "ignore_uid" ) == 0) {
+ i++;
+ if (i == argc) {
+ pam_afs_syslog(LOG_ERR, PAMAFS_IGNOREUID, "ignore_uid missing argument");
+ ignore_uid = 0;
+ } else {
+ ignore_uid = 1;
+ ignore_uid_id = (uid_t) strtol(argv[i], (char**)NULL, 10);
+ if ( (ignore_uid_id < 0) || (ignore_uid_id > IGNORE_MAX)) {
+ ignore_uid = 0;
+ pam_afs_syslog(LOG_ERR, PAMAFS_IGNOREUID, argv[i]);
+ }
+ }
+ } else if (strcasecmp(argv[i], "refresh_token" ) == 0) {
+ refresh_token = 1;
+ } else if (strcasecmp(argv[i], "set_token" ) == 0) {
+ set_token = 1;
+ } else if (strcasecmp(argv[i], "dont_fork" ) == 0) {
+ if (!use_klog) dont_fork = 1;
+ else pam_afs_syslog(LOG_ERR, PAMAFS_CONFLICTOPT, "dont_fork");
+ } else if (strcasecmp(argv[i], "use_klog" ) == 0) {
+ if (!dont_fork) use_klog = 1;
+ else pam_afs_syslog(LOG_ERR, PAMAFS_CONFLICTOPT, "use_klog");
} else if (strcasecmp(argv[i], "setenv_password_expires") == 0) {
set_expires = 1;
} else {
/* so turn that flag off right now. */
if (use_first_pass) try_first_pass = 0;
- pam_afs_syslog(LOG_DEBUG, PAMAFS_OPTIONS, nowarn, use_first_pass, try_first_pass);
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ pam_afs_syslog(LOG_DEBUG, PAMAFS_OPTIONS, nowarn, use_first_pass, try_first_pass, ignore_uid, ignore_uid_id, refresh_token, set_token, dont_fork, use_klog);
/* Try to get the user-interaction info, if available. */
- errcode = pam_get_item(pamh, PAM_CONV, (void **) &pam_convp);
+ errcode = pam_get_item(pamh, PAM_CONV, (const void **) &pam_convp);
if (errcode != PAM_SUCCESS) {
pam_afs_syslog(LOG_WARNING, PAMAFS_NO_USER_INT);
pam_convp = NULL;
}
/* Who are we trying to authenticate here? */
- if ((errcode = pam_get_user(pamh, &user, "login: ")) != PAM_SUCCESS) {
+ if ((errcode = pam_get_user(pamh, (const char **)&user, "login: ")) != PAM_SUCCESS) {
pam_afs_syslog(LOG_ERR, PAMAFS_NOUSER, errcode);
RET(PAM_USER_UNKNOWN);
}
- if ((!strncmp ("root", user, 4)) && trust_root) {
- pam_afs_syslog(LOG_INFO, PAMAFS_TRUSTROOT, user);
- RET(PAM_SUCCESS);
- }
-
- pam_afs_syslog(LOG_DEBUG, PAMAFS_USERNAMEDEBUG, user);
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ pam_afs_syslog(LOG_DEBUG, PAMAFS_USERNAMEDEBUG, user);
/*
* If the user has a "local" (or via nss, possibly nss_dce) pwent,
* and its uid==0, and "ignore_root" was given in pam.conf,
* ignore the user.
*/
+ /* enhanced: use "ignore_uid <number>" to specify the largest uid
+ * which should be ignored by this module
+ */
#if defined(AFS_HPUX_ENV)
#if defined(AFS_HPUX110_ENV)
i = getpwnam_r(user, &unix_pwd, upwd_buf, sizeof(upwd_buf), &upwd);
if ( i == 0 ) /* getpwnam_r success */
upwd = &unix_pwd;
#endif /* else AFS_HPUX110_ENV */
- if (ignore_root && i == 0 && upwd->pw_uid == 0) {
+ if (ignore_uid && i == 0 && upwd->pw_uid <= ignore_uid_id) {
pam_afs_syslog(LOG_INFO, PAMAFS_IGNORINGROOT, user);
RET(PAM_AUTH_ERR);
}
#else
upwd = getpwnam_r(user, &unix_pwd, upwd_buf, sizeof(upwd_buf));
#endif
- if (upwd != NULL && upwd->pw_uid == 0) {
- if (ignore_root) {
- pam_afs_syslog(LOG_INFO, PAMAFS_IGNORINGROOT, user);
- RET(PAM_AUTH_ERR);
- } else if (trust_root && !catch_su) {
- pam_afs_syslog(LOG_INFO, PAMAFS_TRUSTROOT, user);
- RET(PAM_SUCCESS);
- }
+ if (ignore_uid && upwd != NULL && upwd->pw_uid <= ignore_uid_id) {
+ pam_afs_syslog(LOG_INFO, PAMAFS_IGNORINGROOT, user);
+ RET(PAM_AUTH_ERR);
}
#endif
- errcode = pam_get_item(pamh, PAM_AUTHTOK, (void **) &password);
+ errcode = pam_get_item(pamh, PAM_AUTHTOK, (const void **) &password);
if (errcode != PAM_SUCCESS || password == NULL) {
if (use_first_pass) {
pam_afs_syslog(LOG_ERR, PAMAFS_PASSWD_REQ, user);
RET(PAM_AUTH_ERR);
}
password = NULL; /* In case it isn't already NULL */
- pam_afs_syslog(LOG_DEBUG, PAMAFS_NOFIRSTPASS, user);
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ pam_afs_syslog(LOG_DEBUG, PAMAFS_NOFIRSTPASS, user);
} else if (password[0] == '\0') {
/* Actually we *did* get one but it was empty. */
torch_password = 0;
pam_afs_syslog(LOG_INFO, PAMAFS_NILPASSWORD, user);
RET(PAM_NEW_AUTHTOK_REQD);
} else {
- pam_afs_syslog(LOG_DEBUG, PAMAFS_GOTPASS, user);
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ pam_afs_syslog(LOG_DEBUG, PAMAFS_GOTPASS, user);
torch_password = 0;
got_authtok = 1;
}
* this storage, copy it to a buffer that won't need to be freed
* later, and free this storage now.
*/
+
strncpy(my_password_buf, password, sizeof(my_password_buf));
my_password_buf[sizeof(my_password_buf)-1] = '\0';
memset(password, 0, strlen(password));
free(password);
password = my_password_buf;
+ }
+ /* Be sure to allocate a PAG here if we should set a token,
+ * All of the remaining stuff to authenticate the user and to
+ * get a token is done in a child process - if not suppressed by the config,
+ * see below
+ * But dont get a PAG if the refresh_token option was set
+ * We have to do this in such a way because some
+ * apps (such as screensavers) wont call setcred but authenticate :-(
+ */
+ if (!refresh_token) {
+ setpag();
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ syslog(LOG_DEBUG, "New PAG created in pam_authenticate()");
}
+ if (!dont_fork) {
/* Prepare for fork(): set SIGCHLD signal handler to default */
sigemptyset(&newAction.sa_mask);
newAction.sa_handler = SIG_DFL;
* memory/sockets allocated will get cleaned up when the child
* exits: defect 11686.
*/
+ if (use_klog) { /* used by kdm 2.x */
+ if (refresh_token || set_token) {
+ i = do_klog(user, password, NULL);
+ } else {
+ i = do_klog(user, password, "00:00:01");
+ ktc_ForgetAllTokens();
+ }
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ syslog(LOG_DEBUG, "do_klog returned %d", i);
+ auth_ok = i ? 0 : 1;
+ } else {
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ syslog(LOG_DEBUG, "forking ...");
cpid = fork();
if (cpid <= 0) { /* The child process */
- code = ka_VerifyUserPassword(KA_USERAUTH_VERSION + KA_USERAUTH_DOSETPAG,
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ syslog(LOG_DEBUG, "in child");
+ if (refresh_token || set_token)
+ code = ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION,
+ user, /* kerberos name */
+ (char *)0, /* instance */
+ (char *)0, /* realm */
+ password, /* password */
+ 0, /* default lifetime */
+ &password_expires,
+ 0, /* spare 2 */
+ &reason /* error string */ );
+ else
+ code = ka_VerifyUserPassword(KA_USERAUTH_VERSION,
user, /* kerberos name */
(char *)0, /* instance */
(char *)0, /* realm */
} else {
auth_ok = 1;
}
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ syslog(LOG_DEBUG, "child: auth_ok=%d", auth_ok);
if (cpid == 0) exit(auth_ok);
} else {
do {
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ syslog(LOG_DEBUG, "in parent, waiting ...");
rcpid = waitpid(cpid, &status, 0);
} while ((rcpid == -1) && (errno == EINTR));
} else {
auth_ok = 0;
}
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ syslog(LOG_DEBUG, "parent: auth_ok=%d", auth_ok);
+ }
}
-
/* Restore old signal handler */
code = sigaction(SIGCHLD, &origAction, (struct sigaction *)0);
if (code) {
pam_afs_syslog(LOG_ERR, PAMAFS_PAMERROR, errno);
}
+ } else { /* dont_fork, used by httpd */
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ syslog(LOG_DEBUG, "dont_fork");
+ if (refresh_token || set_token)
+ code = ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION,
+ user, /* kerberos name */
+ (char *)0, /* instance */
+ (char *)0, /* realm */
+ password, /* password */
+ 0, /* default lifetime */
+ &password_expires,
+ 0, /* spare 2 */
+ &reason /* error string */ );
+ else
+ code = ka_VerifyUserPassword(KA_USERAUTH_VERSION,
+ user, /* kerberos name */
+ (char *)0, /* instance */
+ (char *)0, /* realm */
+ password, /* password */
+ 0, /* spare 2 */
+ &reason /* error string */ );
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ syslog(LOG_DEBUG, "dont_fork, code = %d",code);
+ if (code) {
+ pam_afs_syslog(LOG_ERR, PAMAFS_LOGIN_FAILED, user, reason);
+ auth_ok = 0;
+ } else {
+ auth_ok = 1;
+ }
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ syslog(LOG_DEBUG, "dont_fork: auth_ok=%d", auth_ok);
+ }
if (!auth_ok && try_first_pass) {
password = NULL;
}
/* We don't care if this fails; all we can do is try. */
- if (auth_ok && !got_authtok) {
+ /* It is not reasonable to store the password only if it was correct
+ * because it could satisfy another module that is called in the chain
+ * after pam_afs
+ */
+ if (!got_authtok) {
torch_password = 0;
- pam_set_item(pamh, PAM_AUTHTOK, password);
+ (void) pam_set_item(pamh, PAM_AUTHTOK, password);
}
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ syslog(LOG_DEBUG, "leaving auth: auth_ok=%d", auth_ok);
+ if (code == KANOENT) RET(PAM_USER_UNKNOWN);
RET(auth_ok ? PAM_SUCCESS : PAM_AUTH_ERR);
out:
"AFS not available", /* 10: AFS_UNAVAIL */
"AFS error code 0x%x", /* 11: AFS_ERROR */
"AFS Authentication succeeded.\n", /* 12: LOGIN_OK */
- "AFS Authentication failed for user %s %s\n",
+ "AFS Authentication failed for user %s. %s\n",
/* 13: LOGIN_FAILED */
"AFS PAM error, code=%d", /* 14: PAMERROR */
"AFS uid exceeds OS bounds.\n", /* 15: UID_OVERFLOW */
"The AFS PAM module may not be used from a non-MT program.\n",
/* 16: NON_MT_PROG */
- "AFS Options: nowarn=%d, use_first_pass=%d, try_first_pass=%d",
+ "AFS Options: nowarn=%d, use_first_pass=%d, try_first_pass=%d, ignore_uid = %d, ignore_uid_id = %d, refresh_token=%d, set_token=%d, dont_fork=%d, use_klog=%d",
/* 17: OPTIONS */
"AFS No pam_conv conversation structure found; no user interaction",
/* 18: NO_USER_INT */
"AFS ReInitializing creds for user %s\n", /* 31: REINITCRED */
"AFS Failed to set PASSWORD_EXPIRES for user %s\n",
/* 32: PASSEXPFAIL */
- "",
- /* 33: */
- "",
- /* 34: */
- "AFS blindly trusting user %s\n", /* 35: TRUSTROOT */
- "New AFS Password: ", /* 36: NEW_PWD_PROMPT */
- "New AFS Password (again): ", /* 37: VERIFY_PWD_PROMPT */
- "Failed to change AFS password", /* 38: KRBPASS_FAIL */
- "Missing PAM flag: %s", /* 39: FLAGS */
- "ka error, code=%d", /* 40: KAERROR */
- "Passwords are not equal" /* 41: NE_PASSWORD */
+ "AFS Failed to chown krb ticketfile\n", /* 33: CHOWNKRB */
+ "AFS Failed to set KRBTKTFILE\n", /* 34: KRBFAIL */
+ "AFS Unknown remaining lifetime %s using default %d seconds\n",
+ /* 35: REMAINLIFETIME */
+ "AFS Session closed", /* 36: SESSIONCLOSED1 */
+ "AFS Session closed, Tokens destroyed\n", /* 37: SESSIONCLOSED2 */
+ "AFS Option conflict dont_fork and use_klog: %s\n",
+ /* 38: CONFLICTOPT */
+ "AFS Unknown uid: %s, option ignored\n",
+ /* 39: IGNOREUID */
+ "New AFS Password: ", /* 40: NEW_PWD_PROMPT */
+ "New AFS Password (again): ", /* 41: VERIFY_PWD_PROMPT */
+ "Failed to change AFS password", /* 42: KRBPASS_FAIL */
+ "Missing PAM flag: %s", /* 43: FLAGS */
+ "ka error, code=%d", /* 44: KAERROR */
+ "Passwords are not equal", /* 45: NE_PASSWORD */
+ "AFS ignoring unregistered user %s\n" /* 46: IGNORE_UNREG */
};
static int num_fallbacks = sizeof(fallback_messages)/sizeof(char *);
#define PAMAFS_PASSEXPFAIL 32 /* "Failed to set PASSWORD_EXPIRES" */
#define PAMAFS_CHOWNKRB 33 /* "Failed to chown krb ticketfile" */
#define PAMAFS_KRBFAIL 34 /* "Failed to set KRBTKTFILE" */
-#define PAMAFS_TRUSTROOT 35 /* "Ignoring superuser %s" */
-#define PAMAFS_NEW_PWD_PROMPT 36 /* "New AFS Password:" */
-#define PAMAFS_VERIFY_PWD_PROMPT 37 /* "New AFS Password (again):" */
-#define PAMAFS_KAPASS_FAIL 38 /* "Failed to change AFS password" */
-#define PAMAFS_FLAGS 39 /* "Missing PAM flag:" */
-#define PAMAFS_KAERROR 40 /* "ka error, code=%d" */
-#define PAMAFS_NE_PASSWORD 41 /* "Passwords are not equal" */
+#define PAMAFS_REMAINLIFETIME 35 /* "Unknown remaining lifetime" */
+#define PAMAFS_SESSIONCLOSED1 36 /* "Session closed" */
+#define PAMAFS_SESSIONCLOSED2 37 /* "Session closed, Tokens destroyed"*/
+#define PAMAFS_CONFLICTOPT 38 /* "Option conflict" */
+#define PAMAFS_IGNOREUID 39 /* "Unknown uid" */
+#define PAMAFS_NEW_PWD_PROMPT 40 /* "New AFS Password:" */
+#define PAMAFS_VERIFY_PWD_PROMPT 41 /* "New AFS Password (again):" */
+#define PAMAFS_KAPASS_FAIL 42 /* "Failed to change AFS password" */
+#define PAMAFS_FLAGS 43 /* "Missing PAM flag:" */
+#define PAMAFS_KAERROR 44 /* "ka error, code=%d" */
+#define PAMAFS_NE_PASSWORD 45 /* "Passwords are not equal" */
+#define PAMAFS_IGNORE_UNREG 46 /* "AFS ignoring unregistered user" */
+
char *pam_afs_message(int msgnum, int *freeit);
void pam_afs_syslog(int priority, int msgid, ...);
if (use_first_pass) try_first_pass = 0;
- pam_afs_syslog(LOG_DEBUG, PAMAFS_OPTIONS, nowarn, use_first_pass, try_first_pass);
- pam_afs_syslog(LOG_DEBUG, PAMAFS_PAMERROR, flags);
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ {
+ pam_afs_syslog(LOG_DEBUG, PAMAFS_OPTIONS, nowarn, use_first_pass, try_first_pass);
+ pam_afs_syslog(LOG_DEBUG, PAMAFS_PAMERROR, flags);
+ }
/* Try to get the user-interaction info, if available. */
errcode = pam_get_item(pamh, PAM_CONV, (const void **) &pam_convp);
RET(PAM_USER_UNKNOWN);
}
- pam_afs_syslog(LOG_DEBUG, PAMAFS_USERNAMEDEBUG, user);
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ pam_afs_syslog(LOG_DEBUG, PAMAFS_USERNAMEDEBUG, user);
/*
* If the user has a "local" (or via nss, possibly nss_dce) pwent,
RET(PAM_AUTH_ERR);
}
password = NULL; /* In case it isn't already NULL */
- pam_afs_syslog(LOG_DEBUG, PAMAFS_NOFIRSTPASS, user);
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ pam_afs_syslog(LOG_DEBUG, PAMAFS_NOFIRSTPASS, user);
} else if (password[0] == '\0') {
/* Actually we *did* get one but it was empty. */
torch_password = 0;
pam_afs_syslog(LOG_INFO, PAMAFS_NILPASSWORD, user);
RET(PAM_NEW_AUTHTOK_REQD);
} else {
+ if (logmask && LOG_MASK(LOG_DEBUG))
pam_afs_syslog(LOG_DEBUG, PAMAFS_GOTPASS, user);
torch_password = 0;
got_authtok = 1;
#include <security/pam_appl.h>
#include <security/pam_modules.h>
+#include <syslog.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include "afs_message.h"
+#include "afs_util.h"
extern int
pam_sm_open_session(
}
+#define REMAINLIFETIME 300
+
extern int
pam_sm_close_session(
pam_handle_t *pamh,
int argc,
const char **argv)
{
+ int i;
+ int logmask = LOG_UPTO(LOG_INFO);
+ int origmask;
+ int remain = 0;
+ int remainlifetime = REMAINLIFETIME;
+ int no_unlog = 0;
+
+ openlog(pam_afs_ident, LOG_CONS|LOG_PID, LOG_AUTH);
+ origmask = setlogmask(logmask);
+
+ /*
+ * Parse the user options. Log an error for any unknown options.
+ */
+ for (i = 0; i < argc; i++) {
+ if ( strcasecmp(argv[i], "debug" ) == 0) {
+ logmask |= LOG_MASK(LOG_DEBUG);
+ (void) setlogmask(logmask);
+ } else if (strcasecmp(argv[i], "remain" ) == 0) {
+ remain = 1;
+ } else if (strcasecmp(argv[i], "remainlifetime") == 0) {
+ i++;
+ remain = 1;
+ remainlifetime = (int) strtol(argv[i], (char**)NULL, 10);
+ if (remainlifetime == 0)
+ if((errno == EINVAL) || (errno == ERANGE)) {
+ remainlifetime = REMAINLIFETIME;
+ pam_afs_syslog(LOG_ERR, PAMAFS_REMAINLIFETIME, argv[i], REMAINLIFETIME);
+ } else {
+ no_unlog = 0;
+ remain = 0;
+ }
+ } else if (strcmp(argv[i], "no_unlog") == 0) {
+ no_unlog = 1;
+ } else {
+ pam_afs_syslog(LOG_ERR, PAMAFS_UNKNOWNOPT, argv[i]);
+ }
+ }
+
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ syslog(LOG_DEBUG, "pam_afs_session_close: remain: %d, remainlifetime: %d, no_unlog: %d",remain,remainlifetime,no_unlog);
+ if(remain && !no_unlog) {
+ switch (fork()) {
+ case -1 : /* error */
+ return(PAM_SESSION_ERR);
+ case 0 : /* child */
+#ifdef AFS_LINUX20_ENV
+ setpgrp();
+#endif
+ setsid();
+ for (i = 0; i <64; i++) close (i);
+ sleep(remainlifetime);
+ ktc_ForgetAllTokens();
+ pam_afs_syslog(LOG_INFO, PAMAFS_SESSIONCLOSED2);
+ exit(0);
+ default : /* parent */
+ pam_afs_syslog(LOG_INFO, PAMAFS_SESSIONCLOSED1);
+ return(PAM_SUCCESS);
+ }
+ }
+ if (!no_unlog && ktc_ForgetAllTokens())
+ return PAM_SESSION_ERR;
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ syslog(LOG_DEBUG, "pam_afs_session_close: Session closed");
return PAM_SUCCESS;
}
#include <string.h>
#include <pwd.h>
#include <unistd.h>
+#include <errno.h>
#include <afsconfig.h>
#include <afs/param.h>
int origmask;
int logmask = LOG_UPTO(LOG_INFO);
int nowarn = 0;
- int use_first_pass = 1; /* use the password passed in by auth */
+ int use_first_pass = 0; /* use the password passed in by auth */
int try_first_pass = 0;
int got_authtok = 0;
- int ignore_root = 0;
- int trust_root = 0;
+ int ignore_uid = 0;
+ int no_unlog = 0;
+ uid_t ignore_uid_id = 0;
+ int refresh_token = 0;
int set_expires = 0; /* the default is to not to set the env variable */
+ int use_klog = 0;
int i;
struct pam_conv *pam_convp = NULL;
char my_password_buf[256];
} else if (strcasecmp(argv[i], "try_first_pass") == 0) {
try_first_pass = 1;
} else if (strcasecmp(argv[i], "ignore_root" ) == 0) {
- ignore_root = 1;
- } else if (strcasecmp(argv[i], "trust_root" ) == 0) {
- trust_root = 1;
- } else if (strcasecmp(argv[i], "catch_su" ) == 0) {
- use_first_pass = 0;
+ ignore_uid = 1;
+ ignore_uid_id = 0;
+ } else if (strcasecmp(argv[i], "ignore_uid" ) == 0) {
+ i++;
+ if (i == argc) {
+ pam_afs_syslog(LOG_ERR, PAMAFS_IGNOREUID, "ignore_uid missing argument");
+ ignore_uid = 0;
+ } else {
+ ignore_uid = 1;
+ ignore_uid_id = (uid_t) strtol(argv[i], (char**)NULL, 10);
+ if ( (0 > ignore_uid_id) || (ignore_uid_id > IGNORE_MAX) ) {
+ ignore_uid = 0;
+ pam_afs_syslog(LOG_ERR, PAMAFS_IGNOREUID, argv[i]);
+ }
+ }
+ } else if (strcasecmp(argv[i], "no_unlog") == 0) {
+ no_unlog = 1;
+ } else if (strcasecmp(argv[i], "refresh_token" ) == 0) {
+ refresh_token = 1;
+ } else if (strcasecmp(argv[i], "set_token" ) == 0) {
+ ;
+ } else if (strcasecmp(argv[i], "dont_fork" ) == 0) {
+ ;
+ } else if (strcasecmp(argv[i], "use_klog" ) == 0) {
+ use_klog = 1;
} else if (strcasecmp(argv[i], "setenv_password_expires")==0) {
set_expires = 1;
} else {
if (use_first_pass) try_first_pass = 0;
- pam_afs_syslog(LOG_DEBUG, PAMAFS_OPTIONS, nowarn, use_first_pass, try_first_pass);
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ pam_afs_syslog(LOG_DEBUG, PAMAFS_OPTIONS, nowarn, use_first_pass, try_first_pass, ignore_uid, ignore_uid_id, 8, 8, 8, 8);
/* Try to get the user-interaction info, if available. */
- errcode = pam_get_item(pamh, PAM_CONV, (void **) &pam_convp);
+ errcode = pam_get_item(pamh, PAM_CONV, (const void **) &pam_convp);
if (errcode != PAM_SUCCESS) {
+ if (logmask && LOG_MASK(LOG_DEBUG))
pam_afs_syslog(LOG_DEBUG, PAMAFS_NO_USER_INT);
pam_convp = NULL;
}
/* Who are we trying to authenticate here? */
- if ((errcode = pam_get_user(pamh, &user, "AFS username:")) != PAM_SUCCESS) {
+ if ((errcode = pam_get_user(pamh, (const char **)&user, "AFS username:")) != PAM_SUCCESS) {
pam_afs_syslog(LOG_ERR, PAMAFS_NOUSER, errcode);
RET(PAM_USER_UNKNOWN);
}
* and its uid==0, and "ignore_root" was given in pam.conf,
* ignore the user.
*/
+ /* enhanced: use "ignore_uid <number>" to specify the largest uid
+ * which should be ignored by this module
+ */
#if defined(AFS_HPUX_ENV)
#if defined(AFS_HPUX110_ENV)
i = getpwnam_r(user, &unix_pwd, upwd_buf, sizeof(upwd_buf), &upwd);
if ( i == 0 ) /* getpwnam_r success */
upwd = &unix_pwd;
#endif /* AFS_HPUX110_ENV */
- if (ignore_root && i == 0 && upwd->pw_uid == 0) {
+ if (ignore_uid && i == 0 && upwd->pw_uid <= ignore_uid_id) {
pam_afs_syslog(LOG_INFO, PAMAFS_IGNORINGROOT, user);
RET(PAM_AUTH_ERR);
}
#else
upwd = getpwnam_r(user, &unix_pwd, upwd_buf, sizeof(upwd_buf));
#endif
- if (upwd != NULL && upwd->pw_uid == 0) {
- if (ignore_root) {
+ if (ignore_uid && upwd != NULL && upwd->pw_uid <= ignore_uid_id) {
pam_afs_syslog(LOG_INFO, PAMAFS_IGNORINGROOT, user);
RET(PAM_AUTH_ERR);
- } else if (trust_root) {
- pam_afs_syslog(LOG_INFO, PAMAFS_TRUSTROOT, user);
- RET(PAM_SUCCESS);
- }
}
#endif
if (flags & PAM_DELETE_CRED) {
+ if (logmask && LOG_MASK(LOG_DEBUG))
pam_afs_syslog(LOG_DEBUG, PAMAFS_DELCRED, user);
RET(PAM_SUCCESS);
} else if (flags & PAM_REINITIALIZE_CRED) {
+ if (logmask && LOG_MASK(LOG_DEBUG))
pam_afs_syslog(LOG_DEBUG, PAMAFS_REINITCRED, user);
RET(PAM_SUCCESS);
} else { /* flags are PAM_REFRESH_CRED, PAM_ESTABLISH_CRED, unknown */
+ if (logmask && LOG_MASK(LOG_DEBUG))
pam_afs_syslog(LOG_DEBUG, PAMAFS_ESTABCRED, user);
errcode = pam_get_data(pamh, pam_afs_lh, (const void **) &password);
RET(PAM_AUTH_ERR);
}
password = NULL; /* In case it isn't already NULL */
- pam_afs_syslog(LOG_DEBUG, PAMAFS_NOFIRSTPASS, user);
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ pam_afs_syslog(LOG_DEBUG, PAMAFS_NOFIRSTPASS, user);
} else if (password[0] == '\0') {
/* Actually we *did* get one but it was empty. */
got_authtok = 1;
pam_afs_syslog(LOG_ERR, PAMAFS_PASSWD_REQ, user);
RET(PAM_NEW_AUTHTOK_REQD);
}
- pam_afs_syslog(LOG_DEBUG, PAMAFS_NILPASSWORD, user);
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ pam_afs_syslog(LOG_DEBUG, PAMAFS_NILPASSWORD, user);
} else {
+ if (logmask && LOG_MASK(LOG_DEBUG))
pam_afs_syslog(LOG_DEBUG, PAMAFS_GOTPASS, user);
torch_password = 0;
got_authtok = 1;
RET(PAM_AUTH_ERR);
}
if (password[0] == '\0') {
+ if (logmask && LOG_MASK(LOG_DEBUG))
pam_afs_syslog(LOG_DEBUG, PAMAFS_NILPASSWORD);
RET(PAM_NEW_AUTHTOK_REQD);
}
* this storage, copy it to a buffer that won't need to be freed
* later, and free this storage now.
*/
+
strncpy(my_password_buf, password, sizeof(my_password_buf));
my_password_buf[sizeof(my_password_buf)-1] = '\0';
memset(password, 0, strlen(password));
free(password);
password = my_password_buf;
}
+ /*
+ * We only set a PAG here, if we haven't got one before in
+ * pam_sm_authenticate() or if it was destroyed by the application
+ */
+ if ((!refresh_token) && (getPAG() == -1)) {
+ if (logmask && LOG_MASK(LOG_DEBUG))
+ syslog(LOG_DEBUG, "New PAG created in pam_setcred()");
+ setpag();
+ }
if ( flags & PAM_REFRESH_CRED ) {
+ if (use_klog) {
+ auth_ok = do_klog(user, password, "00:00:01");
+ ktc_ForgetAllTokens();
+ } else {
if ( ka_VerifyUserPassword(
- KA_USERAUTH_VERSION + KA_USERAUTH_DOSETPAG,
+ KA_USERAUTH_VERSION,
user, /* kerberos name */
(char *)0, /* instance */
(char *)0, /* realm */
auth_ok = 1;
}
}
+ }
if ( flags & PAM_ESTABLISH_CRED ) {
+ if (use_klog) auth_ok = do_klog(user, password, NULL);
+ else {
if ( ka_UserAuthenticateGeneral(
- KA_USERAUTH_VERSION + KA_USERAUTH_DOSETPAG,
+ KA_USERAUTH_VERSION,
user, /* kerberos name */
(char *)0, /* instance */
(char *)0, /* realm */
auth_ok = 1;
}
}
+ }
if (!auth_ok && try_first_pass) {
password = NULL;
goto try_auth;
}
- if (auth_ok && !got_authtok) {
- torch_password = 0;
- (void) pam_set_item(pamh, PAM_AUTHTOK, password);
- }
+ /* pam_sm_authenticate should have set this
+ * if (auth_ok && !got_authtok) {
+ * torch_password = 0;
+ * (void) pam_set_item(pamh, PAM_AUTHTOK, password);
+ * }
+ */
if (auth_ok) {
- if (set_expires && (password_expires >= 0) ) {
+ if (set_expires && !use_klog && (password_expires >= 0) ) {
strcpy(sbuffer, "PASSWORD_EXPIRES=");
strcat(sbuffer, cv2string(&sbuffer[100], password_expires));
errcode = pam_putenv( pamh, sbuffer);
pam_afs_syslog(LOG_ERR, PAMAFS_PASSEXPFAIL, user);
}
#if defined(AFS_KERBEROS_ENV)
- if (upwd)
- {
+ if (!use_klog) {
+ if (upwd) {
if ( chown(ktc_tkt_string(), upwd->pw_uid, upwd->pw_gid) < 0 )
pam_afs_syslog(LOG_ERR, PAMAFS_CHOWNKRB, user);
sprintf(sbuffer, "KRBTKFILE=%s", ktc_tkt_string());
errcode = pam_putenv( pamh, sbuffer);
if ( errcode != PAM_SUCCESS )
pam_afs_syslog(LOG_ERR, PAMAFS_KRBFAIL, user);
+ }
}
#endif
#include <stdio.h>
#include <assert.h>
+#include <unistd.h>
+#include <errno.h>
+#include <syslog.h>
#include <security/pam_appl.h>
#include <afsconfig.h>
#include <afs/param.h>
+#include <sys/wait.h>
RCSID("$Header$");
#if !defined(AFS_HPUX110_ENV)
/* For HP 11.0, this function is in util/hputil.c */
-sigvec()
+sigvec(int sig, const struct sigvec* vec, struct sigvec* ovec)
{
assert(0);
}
#endif /* AFS_HPUX110_ENV */
-sigsetmask()
+sigsetmask(int mask)
{
assert(0);
}
return tp;
}
+int do_klog(const char* user, const char* password, const char* lifetime)
+{
+pid_t pid;
+int pipedes[2];
+int status;
+char* argv[32];
+int argc = 0;
+char* klog_prog;
+int ret = 1;
+
+#if defined(AFS_KERBEROS_ENV)
+ klog_prog = KLOGKRB;
+#else
+ klog_prog = KLOG;
+#endif
+ if (access(klog_prog, X_OK) != 0) {
+ syslog(LOG_ERR, "can not access klog program '%s'", KLOG);
+ goto out;
+ }
+#if defined(AFS_KERBEROS_ENV)
+ argv[argc++] = "klog.krb";
+
+#else
+ argv[argc++] = "klog";
+#endif
+ argv[argc++] = (char*)user;
+ argv[argc++] = "-silent";
+ argv[argc++] = "-pipe";
+ if (lifetime != NULL) {
+ argv[argc++] = "-lifetime";
+ argv[argc++] = (char*)lifetime;
+ }
+ argv[argc] = NULL;
+
+ if (pipe(pipedes) != 0) {
+ syslog(LOG_ERR, "can not open pipe: %s", strerror(errno));
+ goto out;
+ }
+ pid = fork();
+ switch(pid) {
+ case (-1): /* Error: fork failed */
+ syslog(LOG_ERR, "fork failed: %s", strerror(errno));
+ goto out;
+ case (0) : /* child */
+ close(0);
+ dup(pipedes[0]);
+ close(pipedes[0]);
+ close(1);
+ dup(pipedes[1]);
+ close(pipedes[1]);
+ execv(klog_prog, argv);
+ /* notreached */
+ syslog(LOG_ERR, "execv failed: %s", strerror(errno));
+ close(0);
+ close(1);
+ goto out;
+ default :
+ write(pipedes[1], password, strlen(password));
+ write(pipedes[1], "\n", 1);
+ close(pipedes[0]);
+ close(pipedes[1]);
+ if (pid != wait(&status)) return(0);
+ if (WIFEXITED(status)) {
+ ret = WEXITSTATUS(status);
+ goto out;
+ }
+ syslog(LOG_NOTICE, "%s for %s failed", klog_prog, user) ;
+ }
+out:
+ /* syslog(LOG_DEBUG, "do_klog returns %d", ret); */
+ return(ret);
+}
+
+/* get the current AFS pag for the calling process */
+static afs_int32 curpag()
+{
+ gid_t groups[30];
+ afs_uint32 g0, g1;
+ afs_uint32 h, l, ret;
+
+ if (getgroups(sizeof groups/sizeof groups[0], groups) < 2) return 0;
+
+ g0 = groups[0] & 0xffff;
+ g1 = groups[1] & 0xffff;
+ g0 -= 0x3f00;
+ g1 -= 0x3f00;
+ if (g0 < 0xc000 && g1 < 0xc000) {
+ l = ((g0 & 0x3fff) << 14) | (g1 & 0x3fff);
+ h = (g0 >> 14);
+ h = (g1 >> 14) + h + h + h;
+ ret = ((h << 28) | l);
+ /* Additional testing */
+ if (((ret >> 24) & 0xff) == 'A')
+ return ret;
+ else
+ return -1;
+ }
+ return -1;
+}
+
+/* Returns the AFS pag number, if any, otherwise return -1 */
+afs_int32 getPAG()
+{
+ afs_int32 pag;
+
+ pag = curpag();
+ if (pag == 0 || pag == -1)
+ return -1;
+
+ /* high order byte is always 'A'; actual pag value is low 24 bits */
+ return (pag & 0xFFFFFF);
+}
extern char* cv2string();
+#define KLOG "/usr/afsws/bin/klog"
+#define KLOGKRB "/usr/afsws/bin/klog.krb"
+#define UNLOG "/usr/afsws/bin/unlog"
+#define IGNORE_MAX 1000
+
#if defined(AFS_HPUX_ENV)
#if !defined(AFS_HPUX110_ENV)
int authenticated = 0;
int retcode;
char *username;
+ int setcred = 1;
if (argc < 2 || argc > 3) {
fprintf(stderr, "Usage: %s [-u] <user>\n", argv[0]);
fprintf(stderr, "Usage: %s [-u] <user>\n", argv[0]);
exit(1);
}
- service = "unixtest";
+ /* service = "unixtest"; */
+ setcred = 0;
username = argv[2];
} else {
username = argv[1];
/* pam_open_session */
+ if (setcred)
if ((retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS) {
fprintf(stderr, "pam_setcred returned %d.\n", retcode);
pam_end(pamh, PAM_ABORT);
exit(1);
}
+ if ((retcode = pam_open_session(pamh, PAM_SILENT)) != PAM_SUCCESS) {
+ fprintf(stderr, "pam_open_session returned %d.\n", retcode);
+ pam_end(pamh, PAM_ABORT);
+ exit(1);
+ }
pam_end(pamh, PAM_SUCCESS);
putenv(new_envstring);