Ejemplo n.º 1
0
PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh,
                                   int flags, int argc, const char **argv)
{

    const char *user = NULL, *passwd = NULL;
    struct passwd *pwd;
    int rval, status;
    pid_t pid;


    // For checking mount paths: (mount from + target)
    char path[PATH_MAX];
    char targetpath[PATH_MAX];
    char encfs_options[USERNAME_MAX];
    char fuse_options[USERNAME_MAX];
    char *targetpath_store;

    strcpy(default_encfs_options, "");
    strcpy(default_fuse_options, "");

    // For execing:
    char *arg[USERNAME_MAX];
    int arg_pos = 0;
    int i;
    int inpipe[2], outpipe[2];

    rval = pam_get_user(pamh, &user, NULL);
    if ((rval != PAM_SUCCESS) || (!user))
    {
        _pam_log(LOG_ERR, "can't get username: %s", pam_strerror(pamh, rval));
        return PAM_AUTH_ERR;
    }

    rval = pam_get_item(pamh, PAM_AUTHTOK, (const void **) (void *) &passwd);
    if (rval != PAM_SUCCESS)
    {
        _pam_log(LOG_ERR, "Could not retrieve user's password");
        return PAM_AUTH_ERR;
    }

    if (!passwd)
    {
        rval = _set_auth_tok(pamh, flags, argc, argv);
        if (rval != PAM_SUCCESS)
        {
            return rval;
        }
        rval =
            pam_get_item(pamh, PAM_AUTHTOK, (const void **) (void *) &passwd);
        if (rval != PAM_SUCCESS || passwd == NULL)
        {
            _pam_log(LOG_ERR, "Could not retrieve user's password");
            return PAM_AUTH_ERR;
        }
    }
    if ((pwd = getpwnam(user)) == NULL)
    {
        _pam_log(LOG_ERR, "Could not getpwnam");
        return PAM_AUTH_ERR;
    }

    // Read configfile  
    if (!readconfig
        (pwd, pamh, pwd->pw_name, path, targetpath, encfs_options,
         fuse_options))
    {
        // DEBUG _pam_log(LOG_ERR,"No entry for user found in log");
        return PAM_IGNORE;
    }
    //DEBUG _pam_log(LOG_ERR,"Username : %s, Encpath : %s, Targetmount : %s",pwd->pw_name,path,targetpath);

    //Store targetpath
    targetpath_store = strdup(targetpath);
    if ((i =
         pam_set_data(pamh, "encfs_targetpath", targetpath_store,
                      targetpath_cleanup)) != PAM_SUCCESS)
    {
        _pam_log(LOG_ERR, "Storing targetpath FAIL");
        free(targetpath_store);
        return i;
    }

    // Check if we're mounted already.
    if (checkmnt(targetpath))
    {
        //DEBUG _pam_log(LOG_ERR,"Already mounted");
        return PAM_IGNORE;
    }



    /*  _pam_log(LOG_ERR,"Config output for %s:",user);
       _pam_log(LOG_ERR,"  path       : %s",path);
       _pam_log(LOG_ERR,"  targetpath : %s",targetpath);
       _pam_log(LOG_ERR,"  encfs      : %s %s",default_encfs_options,encfs_options);
       _pam_log(LOG_ERR,"  fuse       : %s %s",default_fuse_options,fuse_options); */


    arg_pos += buildCmd(arg, arg_pos, "encfs");
    arg_pos += buildCmd(arg, arg_pos, "-S");
    arg_pos += buildCmd(arg, arg_pos, default_encfs_options);
    arg_pos += buildCmd(arg, arg_pos, encfs_options);
    arg_pos += buildCmd(arg, arg_pos, path);
    arg_pos += buildCmd(arg, arg_pos, targetpath);

    if (strlen(default_fuse_options) > 0 && strlen(fuse_options) > 0)
        strcat(fuse_options, ",");

    strcat(fuse_options,default_fuse_options);
    if (strlen(fuse_options) > 0) {
        arg_pos += buildCmd(arg, arg_pos, "--");
        arg_pos += buildCmd(arg, arg_pos, "-o");
        arg_pos += buildCmd(arg, arg_pos, fuse_options);
    }
    arg[arg_pos] = NULL;

    /*  printf("Arguments : ");
       for (i = 0; i < arg_pos+1;i++) {
       _pam_log(LOG_ERR,"Data : %s",arg[i]);
       }

       _pam_log(LOG_ERR,"Number of arguments : %d",arg_pos); */


    /*  arg[0] = cmd;
       arg[1] = params;
       //  arg[2] = params2;
       arg[2] = params3;
       arg[3] = path;
       arg[4] = targetpath;
       arg[5] = fuseparams;
       arg[6] = fuseparams2;
       arg[7] = NULL; */



    if (pipe(inpipe) || pipe(outpipe))
    {
        _pam_log(LOG_ERR, "Failed to create pipe");
        return PAM_IGNORE;
    }

    // Execute 
    switch (pid = fork())
    {
        case -1:
            _pam_log(LOG_ERR, "Fork failed");
            return PAM_SERVICE_ERR;
        case 0:

            if (drop_permissions == 1)
                if ((initgroups(pwd->pw_name, pwd->pw_gid) == -1)
                    || (setgid(pwd->pw_gid) == -1)
                    || (setuid(pwd->pw_uid) == -1))
                {
                    _pam_log(LOG_ERR, "Dropping permissions failed");
                    return PAM_SERVICE_ERR;
                }
            close(outpipe[WRITE_END]);
            dup2(outpipe[READ_END], fileno(stdin));
            close(outpipe[READ_END]);

            close(inpipe[READ_END]);
            dup2(inpipe[WRITE_END], fileno(stdout));
            close(inpipe[WRITE_END]);

            // For some reason the current directory has to be set to targetpath (or path?) before exec'ing encfs through gdm
            chdir(targetpath);
            execvp("encfs", arg);
            char errstr[128];

            snprintf(errstr, 127, "%d - %s", errno, strerror(errno));
            _pam_log(LOG_ERR, "Exec failed - %s", errstr);
            exit(127);
    }

    int len;


    close(inpipe[WRITE_END]);
    close(outpipe[READ_END]);




    if (waitpid(pid, &status, WNOHANG) == 0)
    {
        len = write(outpipe[WRITE_END], passwd, (size_t) strlen(passwd));
        if ((len != (size_t) strlen(passwd))
            || (write(outpipe[WRITE_END], "\n", 1) != 1))
            _pam_log(LOG_ERR, "Did not send password to pipe (%d sent)", len);
        close(outpipe[WRITE_END]);
    }


    if (waitpid_timeout(pid, &status, 0))
    {
        _pam_log(LOG_ERR, "Timed out waiting for encfs, killing\n");
        kill(pid, SIGKILL);
    }

    int exitstatus = WEXITSTATUS(status);
    char buff[512];

    len = read(inpipe[READ_END], &buff, 511);
    close(inpipe[READ_END]);
    buff[len] = 0;
    if (!checkmnt(targetpath) && (len > 0 || exitstatus > 0))
    {
        _pam_log(LOG_ERR, "exitcode : %d, errorstring : %s", exitstatus,
                 buff);
        return PAM_AUTH_ERR;
    }
    else
    {
        return PAM_IGNORE;
    }
    return PAM_AUTH_ERR;
}
Ejemplo n.º 2
0
static int _pam_auth_smb(	pam_handle_t *pamh,
				int flags, 
				int argc,
				const char **argv	) 
{
        int retval;
	struct passwd *pw;
	const char *name;
	char *p, *pp;
	int w,loop;
	const char *salt;
	char server[80],server2[80],domain[80];
	char ntname[32];
	int debug=0, use_first_pass=0;
	int nolocal=0;

#ifdef HAVE_SHADOW_H

	struct spwd *sp;

#endif

	/* Parse Command line options */
  
	for (loop=0; loop<argc; loop++)
	  {
	    if (!strcmp(argv[loop], "debug"))
	      debug=1;
	    else 
	      if (!strcmp(argv[loop], "use_first_pass"))
		use_first_pass=1;
	      else
		if (!strcmp(argv[loop], "nolocal"))
		  nolocal=1;
		else
		  syslog(LOG_AUTHPRIV | LOG_ERR, "pam_smb: Unknown Command Line Option in pam.d : %s", argv[loop]);
	  }
	   
	/* get the user'name' */
	
	if ( (retval = pam_get_user( pamh, &name, "login: "******"x")))
		  {
		    /* TODO: check if password has expired etc. */
		    salt = sp->sp_pwdp;
		  } 
		else
#endif
		  salt = pw->pw_passwd;
	      } 
	    else  
	      return PAM_USER_UNKNOWN;
	    
	    /* The 'always-encrypt' method does not make sense in PAM
	       because the framework requires return of a different
	       error code for non-existant users -- alex */
	    
	    if ( ( !pw->pw_passwd ) && ( !p ) )
	      if ( flags && PAM_DISALLOW_NULL_AUTHTOK )
		return PAM_SUCCESS;
	    
	    pp = crypt(p, salt);
	    
	    if ( strcmp( pp, salt ) == 0 )
	      {
		if (debug) 
		  syslog(LOG_AUTHPRIV | LOG_DEBUG, "pam_smb: Local UNIX username/password pair correct.");
		return  PAM_SUCCESS;
	      }
	    
	    if (debug) {
	      syslog (LOG_AUTHPRIV | LOG_DEBUG, "pam_smb: Local UNIX username/password check incorrect.");
	    }
	  } /* End of Local Section */
	else { /* If Local System Authentication is switched off */
	  if (debug) syslog(LOG_AUTHPRIV | LOG_DEBUG,"No Local authentication done, relying on other modules for password file entry.");
	}

	w=smb_readpamconf(server,server2,domain);
	if (w!=0) 
	  {
	    syslog(LOG_AUTHPRIV | LOG_ALERT, "pam_smb: Missing Configuration file : /etc/pam_smb.conf");
	    return PAM_AUTHINFO_UNAVAIL;
	  }
	
	if (debug) {
	  syslog(LOG_AUTHPRIV | LOG_DEBUG, "pam_smb: Configuration Data, Primary %s, Backup %s, Domain %s.", server, server2, domain);
	}

	w=Valid_User(ntname, p, server, server2,  domain);
		  
	/* Users valid user for return value 0 is success
	   1 and 2 indicate Network and protocol failures and
	   3 is not logged on 
	   */

	switch (w)
	  {
	  case 0 : 
	    if (debug) syslog(LOG_AUTHPRIV | LOG_DEBUG, "pam_smb: Correct NT username/password pair");
	    return PAM_SUCCESS; break;
	  case 1 :
	  case 2 :
	    return PAM_AUTHINFO_UNAVAIL; break;
	  case 3 :
	  default:
	    syslog(LOG_AUTHPRIV | LOG_NOTICE, "pam_smb: Incorrect NT password for username : %s", ntname);
	    return PAM_AUTH_ERR; break;
	  }

  	return PAM_AUTH_ERR;

}
Ejemplo n.º 3
0
/* expected hook for auth service */
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags,
				   int argc, const char **argv) {
    int retval, pcnt, pwdfilename_found;
    const char *name;
    char *password;
    char pwdfilename[PWDFN_LEN];
    char salt[12], stored_crypted_password[CRYPTED_BCPWD_LEN+1];
    char *crypted_password;
    FILE *pwdfile;
    int use_flock = 0;
    int use_delay = 1;
    int temp_result = 0;
    
    /* we require the pwdfile switch and argument to be present, else we don't work */
    /* pcnt is the parameter counter variable for iterating through argv */
    pcnt = pwdfilename_found = 0;
    do {
	/* see if the current parameter looks like "pwdfile" */
	if (strcmp(argv[pcnt],PWDF_PARAM)==0) {
	    /* if argv is long enough, grab the subsequent parameter */
	    if (pcnt+1 < argc) {
		/* make sure we can't overflow */
		strncpy(pwdfilename,argv[++pcnt],PWDFN_LEN);
		/* indicate that we've found it */
		pwdfilename_found = 1;
	    }
	    /* also check for "pwdfile=blah" */
	} else if (strncmp(argv[pcnt],PWDF_PARAM "=",sizeof(PWDF_PARAM "=")-1)==0) {
	    /* make sure we can't overflow */
	    strncpy(pwdfilename,argv[pcnt]+sizeof(PWDF_PARAM),PWDFN_LEN);
	    /* indicate that we've found it */
	    pwdfilename_found = 1;
	} else if (strcmp(argv[pcnt],FLOCK_PARAM)==0) {
	    /* we have a "flock" parameter */
	    use_flock = 1;
	} else if (strcmp(argv[pcnt],"no" FLOCK_PARAM)==0) {
	    /* or a "noflock" parameter */
	    use_flock = 0;
	} else if (strcmp(argv[pcnt],NODELAY_PARAM)==0) {
	    /* no delay on authentication failure */
	    use_delay = 0;
	}
	
    } while (++pcnt < argc);
    
#ifdef HAVE_PAM_FAIL_DELAY
    if (use_delay) {
	D(("setting delay"));
	(void) pam_fail_delay(pamh, 2000000);   /* 2 sec delay for on failure */
    }
#endif
    
    /* for some or other reason, the password file wasn't specified */
    if (!pwdfilename_found) {
	_pam_log(LOG_ERR,"password file name not specified");
	return PAM_AUTHINFO_UNAVAIL;
    }
    
    /* DEBUG */
    D(_pam_log(LOG_ERR, "password filename extracted"));
    
    /* now try to open the password file */
    if ((pwdfile=fopen(pwdfilename,"r"))==NULL) {
	_pam_log(LOG_ERR,"couldn't open password file %s",pwdfilename);
	return PAM_AUTHINFO_UNAVAIL;
    }
    
    /* set a lock on the password file */
    if (use_flock && lock_fd(fileno(pwdfile)) == -1) {
	_pam_log(LOG_ERR,"couldn't lock password file %s",pwdfilename);
	return PAM_AUTHINFO_UNAVAIL;
    }
    
    /* get user name */
    if ((retval = pam_get_user(pamh,&name,"login: "******"username not found");
	fclose(pwdfile);
	return retval;
    }
    
    
    /* DEBUG */
    D(_pam_log(LOG_ERR,"username is %s", name));
    
    /* get password - code from pam_unix_auth.c */
    pam_get_item(pamh, PAM_AUTHTOK, (void *)&password);
    if (!password) {
	retval = _set_auth_tok(pamh, flags, argc, argv);
	if (retval!=PAM_SUCCESS) {
	    fclose(pwdfile);
	    return retval;
	}
    }
    pam_get_item(pamh, PAM_AUTHTOK, (void *)&password);
    
    if ((retval = pam_get_item(pamh, PAM_AUTHTOK, (void *)&password)) != PAM_SUCCESS) {
	_pam_log(LOG_ERR, "auth token not found");
	fclose(pwdfile);
	return retval;
    }
    
    /* DEBUG */
    D(_pam_log(LOG_ERR,"got password from user", password));
    
    /* now crypt password and compare to the user entry in the password file */
    /* first make sure password is long enough -- may I do this? */
    if (strlen(password)<2 || password==NULL) {
	_pam_log(LOG_ERR,"password too short or NULL");
	fclose(pwdfile);
	return PAM_AUTH_ERR;
    }
    
    /* get the crypted password corresponding to this user */
    if (!fgetpwnam(pwdfile, name, stored_crypted_password)) {
	_pam_log(LOG_ERR,"user not found in password database");
	fclose(pwdfile);
	return PAM_AUTHINFO_UNAVAIL;
    }
    
    /* DEBUG */
    D(_pam_log(LOG_ERR,"got crypted password == '%s'", stored_crypted_password));
    
    
    temp_result = 0;
    
    /* Extract the salt and set the passwd length, depending on MD5 or DES */
    if (strncmp(stored_crypted_password, "$1$", 3) == 0) {
	D(_pam_log(LOG_ERR,"password hash type is 'md5'"));
	/* get out the salt into "salt" */
	strncpy(salt, stored_crypted_password, 11);
	salt[11] = '\0';
	stored_crypted_password[CRYPTED_MD5PWD_LEN] = '\0';
	/* try both md5 crypts */
	crypted_password = Goodcrypt_md5(password, salt);
	if (strcmp(crypted_password, stored_crypted_password) == 0)
	{
	    temp_result = 1;
	}
	else
	{
	    crypted_password = Brokencrypt_md5(password, salt);
	    if (strcmp(crypted_password, stored_crypted_password) == 0)
	    {
		temp_result = 1;
	    }
	}
    } else {
	/* get the salt out into "salt" */
	strncpy(salt, stored_crypted_password, 2);
	salt[2] = '\0';
	stored_crypted_password[CRYPTED_BCPWD_LEN] = '\0';

	if (strlen(stored_crypted_password) <= CRYPTED_DESPWD_LEN) {
	    D(_pam_log(LOG_ERR,"password hash type is 'crypt'"));
	    crypted_password = crypt(password, salt);
	} else {
	    D(_pam_log(LOG_ERR,"password hash type is 'bigcrypt'"));
	    crypted_password = bigcrypt(password, salt);
	}

	if (strcmp(crypted_password, stored_crypted_password) == 0)
	{
	    temp_result = 1;
	}
    }
    
    /* DEBUG */
    D(_pam_log(LOG_ERR,"user password crypted is '%s'", crypted_password));
    
    /* if things don't match up, complain */
    if (!temp_result) 
    {
	_pam_log(LOG_ERR,"wrong password for user %s",name);
	fclose(pwdfile);
	return PAM_AUTH_ERR;
    }
    
    /* DEBUG */
    D(_pam_log(LOG_ERR,"passwords match"));
    
    /* we've gotten here, i.e. authentication was sucessful! */
    fclose(pwdfile);
    return PAM_SUCCESS;
}