Christian Hesse <[email protected]> on Wed, 2012/05/09 11:55:
> Hello everybody,
> 
> This is from man pam_unix:
> > try_first_pass
> >            Before prompting the user for their password, the module first
> > tries the previous stacked module's password in case that satisfies this
> > module as well.
> 
> I think pam_oath has a similar option.
> So I tested with these in my pam configuration:
> 
> auth sufficient pam_unix.so
> -auth required pam_oath.so usersfile=/etc/users.oath digits=6 try_first_pass
> 
> and
> 
> -auth sufficient pam_oath.so usersfile=/etc/users.oath digits=6
> auth required pam_unix.so try_first_pass
> 
> My understanding is that I get one prompt that accepts unix and oath
> password. But obviously this does not work, authentication fails for the
> line containing try_first_pass.
> Anything I misunderstood? How is this expected to work?

I did some debugging... Looks like pam_get_item() at line 161 writes a memory
address to password that is not guaranteed to persist. The memory is
overwritten or cleared in pam_set_item() at line 275, thus the following
strncpy() does not copy anything useful.

The attached patch fixes it for me, though I am not sure this is a 'clean'
way...
-- 
main(a,b){char*/*    Schoene Gruesse                         */c="B?IJj;M"
"EHCX:;";for(a/*    Chris           get my mail address:    */=0;b=c[a++];)
putchar(b-1/(/*               gcc -o sig sig.c && ./sig    */b/42*2-3)*42);}
--- oath-toolkit-1.12.2/pam_oath/pam_oath.c	2012-04-04 11:32:57.000000000 +0200
+++ oath-toolkit-1.12.2/pam_oath/pam_oath.c	2012-05-31 01:27:54.575977370 +0200
@@ -159,6 +159,7 @@ pam_sm_authenticate (pam_handle_t * pamh
   if (cfg.try_first_pass || cfg.use_first_pass)
     {
       retval = pam_get_item (pamh, PAM_AUTHTOK, (const void **) &password);
+      password = strdup(password);
       if (retval != PAM_SUCCESS)
 	{
 	  DBG (("get password returned error: %s",
@@ -314,6 +315,8 @@ done:
   oath_done ();
   free (query_prompt);
   free (onlypasswd);
+  if (cfg.try_first_pass || cfg.use_first_pass)
+	  free(password);
   if (cfg.alwaysok && retval != PAM_SUCCESS)
     {
       DBG (("alwaysok needed (otherwise return with %d)", retval));

Reply via email to