Niedermayer.ca
Published on Niedermayer.ca (https://niedermayer.ca)

Home > User Management System (UMS) -- Detailed System Design > Procedure Model > Shared Library Procedures

Shared Library Procedures

lib/uname_test.pl

Procedure Model

Type:    (  )Web Page              (  )CGI Script              (X)Shared Library      (  )System API

Name: lib/uname_test.pl

Assigned to:

Reference:

Description

This script verifies that a username passed as a string to the function would be a good username. The test of goodness requires that the proposed username is unique to the system (i.e. no existing user has this name), and that the username is comprised of only alphabetic characters, numbers, underscores and dots (period), and that the username is between 4 and 16 characters long. For the purpose of the test, uppercase and lowercase characters are equivalent so that if the user has chosen a username of upper-case characters, these characters will be replaced with their lower-case equivalents.

Implementation Skills

PERL

Parameter List

String containing the proposed username

Called By:

user/validate.cgi
user/upgrade.cgi
lib/uname_generate.pl

Can Call:

 

Function Description

Verify the appropriateness and uniqueness of the proposed username by performing the following steps:

  1. Check that the username is between 4 and 16 characters in length and contains only characters, digits, underscores and dots (periods). If it fails this test, exit this function and return an appropriate error description.
  2. Convert the proposed username to all lowercase letters.
  3. Check that the username is unique within the system. If this test fails, exit the function and return an appropriate error description. This test of uniqueness is met if:
  • There is no existing entry in the /etc/password file with the same username
  • There is no existing entry in the /etc/mail/aliases file such that the proposed username was a previous system username that has since been remapped to a new username.
  • There is no other entry in the User table or Member table with this username such that the same username is in a pending state awaiting another user’s agreement or remittance.
  1. Return a null length string if the proposed username is acceptable to the system.

Possible Exit Conditions and Return Values

  1. If the username is not appropriate, a descriptive error message is returned as a scalar variable.
  2. If the username is appropriate, the function returns a null length string.

Sign Off by:

Project Manager.

 

  • Log in [1] to post comments

lib/uname_generate.pl

Procedure Model

Type:    (  )Web Page              (  )CGI Script              (X)Shared Library      (  )System API

Name: lib/uname_generate.pl

Assigned to:

Reference:

Description

This function returns a string containing the next available sequential username following the format aannn where “a” denotes an alphabetic, lowercase character and “n” denotes a digit. For example, if the last username assigned by this function was aa999, the function will test that ab000 is not assigned and if it is free, will assign it. Otherwise, the function will test for ab001 and so on.

Implementation Skills

PERL

Parameter List

none

Called By:

user/validate.cgi

Can Call:

lib/uname_test.pl
/usr/local/csuite/etc/lastacct

Function Description

  1. Open the /usr/local/csuite/etc/lastacct file if one exists. If this is the first time the script is ever called, this file will have to be created.
  2. The contents of the lastacct file should include the last created username. If it does not, assume that the lastacct has value “aa000.” Read this username into a variable and increment it according to the algorithm described in the description section above. Write this new incremented value back to the lastacct file, deleting all previous content.
  3. Test this newly incremented value using the uname_test.pl function. If this new username passes this test return this new username to the calling procedure. Otherwise, repeat steps 2 and 3 until this test is successful.

Possible Exit Conditions and Return Values

The function returns the value of the next available sequentially assigned username as a scalar value.

Sign Off by:

Project Manager

 

  • Log in [2] to post comments

lib/pw_check

Procedure Model

Type:    (  )Web Page              (  )CGI Script              (X)Shared Library      (  )System API

Name: lib/pw_check

Assigned to:

Reference:

Description

This function takes a string parameter and runs it against the system pw_check utility to see if it is a sufficiently strong password. If not, the function returns a string describing the weakness(es) of the password.

Implementation Skills

C

Parameter List

password- a string containing the password string to test

Called By:

user/validate.cgi

Can Call:

crack.h

Function Description

#include <stdio.h>
#include <stdlib.h>
#include <crack.h>

int main(int argc, char *argv[]) {
   int i;
   char* pw_check;
   char* password;
   char* dict_path = “/usr/lib/cracklib_dict”;
   char* null_string = “”;
   char* bad_usage =
         "Usage: pw_check [password]";

   if (argc != 2) {
      fputs(bad_usage,stdout);
      return (-1);
   }

   password  = argv[1];
   pw_check = FascistCheck(password, dict_path);

   if (pw_check != NULL)
      fputs(pw_check,stdout);
   else fputs(null_string,stdout);

   exit(0);
}

Usage within a PERL or Shell Script:

$output=`pw_check([password])`;

if ($output eq “”) {
   # password is good
}
else {
   # password is bad. Reason is stored in $output
}

Possible Exit Conditions and Return Values

  1. The program returns a –1 if an insufficient number of parameters were passed to the command. The description of the proper way to call the program should be passed through to the calling routine using the stdout handle. Check the contents of the $output variable in the above function description example.
  2. The program returns a 0 if the program is properly called. If the password is sufficiently strong, then an empty string is passed back through the stdout handle. Otherwise, a text string describing the problems with the password are listed. Since multiple problems can exist, these lines will be separated with a newline character (“\n”).

Sign Off by:

Project Manager

 

  • Log in [3] to post comments

lib/Login.pm

Procedure Model

Type:    (  )Web Page              (  )CGI Script              (X)Shared Library      (  )System API

Name: lib/Login.pm

Assigned to:

Reference:

Description

This module manages login sessions for the system. Its public methods are called by CGI scripts to determine if the user is properly authenticated on the system and has currently valid credentials.

The Constructor assumes that the user has been authenticated by the login.cgi script. As such, it accepts the call to create the session token, but does no additional checks on the authenticity of the user.

Implementation Skills

PERL, SQL, MySQL

Parameter List

Username, access_level

Called By:

user/login.cgi
user/upgrade.cgi
user/myacct.cgi
user/quota.cgi
user/passwd.cgi
user/forward.cgi
user/history.cgi
user/filter.cgi

Can Call:

Http_Sessions database.

Function Description

HTTP_Sessions database Sessions table:

+-------------+---------------+------+-----+---------+-------+
| Field       | Type          | Null | Key | Default | Extra |
+-------------+---------------+------+-----+---------+-------+
| User_Name   | varchar(20)   |      | PRI |         |       |
| Session_Tok | varchar(32)   |      |     |         |       |
| Access_Level| int           |      |     | 0       |       |
| TimeStamp   | timestamp(14) | YES  |     | NULL    |       |
+-------------+---------------+------+-----+---------+-------+

Constructor(UserName, Access_Level) method:

  1. Take the username and access_level from the parameter list passed to the function.
  2. Open the sessions database and delete any previous entry for this same username.
  3. Create a session token by MD5 base64 encoding the current timestamp.
  4. Insert a new record into the Sessions table with this User_Name, Session_Token, and Access_Level.
  5. Populate and return a Login object with the User_Name, Session_Token and Access_Level. This object is then used by the calling program to send a Login cookie back to the user’s browser using the format: “<username>:<access_level>:<session_token>

getLogin() method:

  1. Get a reference to the CGI query object and extract the Login cookie from this object.
  2. If no cookie exists, return a null Login object. Otherwise, split the Login cookie using the colons into its username, access_level and session_token values.
  3. Query the Sessions table for a matching token and if one exists populate a new Login object with the values from the database. Otherwise, return a null Login object.

getUserName(Login) method:

  1. Using the Login object passed as a parameter, return the Username string property of the object.

getAccessLevel(Login) method:

  1. Using the Login object passed as a parameter, return the Access_Level integer property of the object.

destroy(UserName) method:

  1. Delete any record in the Sessions table with this UserName and nullify any cookie stored on the browser by returning a new Login cookie with an empty string for its value.

Possible Exit Conditions and Return Values

A Login object with undefined properties indicates that the system failed to find any credentials for this user. This test is usually performed by using the getLogin() method to get a Login object and then calling the getUserName(Login) method with the Login object returned by the getLogin method. If the getUserName method returns an undefined value, then the credentials do not exist or there is a system problem.

Note that this class does not test for the age of a set of credentials although such a test can be included by having the getLogin method test the age of the session token by looking at the timestamp value in the Sessions table.

Sign Off by:

Project Manager.

 

  • Log in [4] to post comments

lib/auth_user

Procedure Model

Type:    (  )Web Page              (  )CGI Script              (X)Shared Library      (  )System API

Name: lib/auth_user

Assigned to:

Description

This suid program takes the username and password and returns a 0 if the username and password match the system password for the stated user. Any other return code indicates an error.

Implementation Skills

C, PAM

Parameter List

Username and password as string values

Called By:

user/login.cgi

Can Call:

PAM system libraries

Function Description

Example of a proper function call from a calling PERL script:

output=`/usr/local/csuite/lib/auth_user $user $passwd `;

/*****************************************************
** Library functions to interact with the Linux-PAM  **
** modules in order to update a user's password on   **
** the system.                                       **
**                                                   **
** Make sure you add the following lines to the      **
** pam.conf file (or equivalent):                    **
** cs_password auth     required                     **
**                    /lib/security/pam_unix_auth.so **
** cs_password account  required                     **
**                    /lib/security/pam_unix_acct.so **
** cs_password password required                     **
**                  /lib/security/pam_unix_passwd.so **
** cs_password session  required                     **
**                    /lib/security/pam_unix_acct.so **
**                                                   **
** Author:      Daryle Niedermayer (dpn)             **
**              daryle@gpfn.ca                       **
** Date:        2002-06-17                           **
**                                                   **
******************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <security/pam_appl.h>
#include <security/pam_misc.h>

#define CS_BAD_DATA               -2
#define CS_BAD_USAGE              -1
#define CS_SUCCESS                0

#define COPY_STRING(s) (s) ? strdup(s) : NULL

/* DEFINE STATIC EXTERNAL STRUCTURES AND VARIABLES 
   SO THAT THEY ONLY HAVE SCOPE WITHIN THE METHODS 
   AND FUNCTIONS OF THIS SOURCE FILE */
static char*        service_name = "cs_password";
static char*        user;
static char*        old_password;
static char*        new_password;
static int PAM_conv (int, const struct pam_message**,
                     struct pam_response**, void*);
static struct pam_conv PAM_converse = {PAM_conv, NULL};

/*************************************************
** PAM Conversation function                    **
*************************************************/
static int PAM_conv (
   int num_msg,
   const struct pam_message **msg,
   struct pam_response **resp, void *appdata_ptr) {

   int replies = 0;
   struct pam_response *reply = NULL;

   reply =
      malloc(sizeof(struct pam_response) * num_msg);
   if (!reply) return PAM_CONV_ERR;

   for (replies = 0; replies < num_msg; replies++) {
      if (! strcmp(msg[replies]->msg,"Password: "))
         reply[replies].resp =
            COPY_STRING(old_password);
      if (! strcmp(msg[replies]->msg,
         "(current) UNIX password: "))
         reply[replies].resp =
            COPY_STRING(old_password);
   }

   *resp = reply;
   return PAM_SUCCESS;
}

/*************************************************
** MAIN PROCEDURE                               **
*************************************************/
int main(int argc, char *argv[]) {

/* DEFINITIONS */
   pam_handle_t*    pamh = NULL;
   int              retval;
   char*            pw_check;
   char*            dict_path = "/usr/lib/cracklib_dict";

/* DETERMINE IF VARIABLE COUNT IS CORRECT */
   if (argc != 3) {
      printf("Usage: auth_user <USER> <PASSWORD>\n");
      exit (CS_BAD_USAGE);
   }

/* PARSE PARAMETERS FROM INPUTS */
   user         = argv[1];        
   old_password = argv[2];

   if (!(user && old_password && strlen(user) && strlen(old_password)))
      exit (CS_BAD_DATA);

/* GET A HANDLE TO A PAM INSTANCE */
   retval = pam_start(service_name, user, &PAM_converse, &pamh);

/* IS THE USER REALLY A USER? */
   if (retval == PAM_SUCCESS)
      retval = pam_authenticate(pamh, 0);
   else return retval;

/* IS USER PERMITTED ACCESS? */
   if (retval == PAM_SUCCESS)
      retval = pam_acct_mgmt(pamh, 0);
   else return retval;

/* CLEAN UP OUR HANDLES AND VARIABLES */
   if (pam_end(pamh, retval) != PAM_SUCCESS)
      pamh = NULL;
   else return retval;
  
   exit (CS_SUCCESS);
}

Possible Exit Conditions and Return Values

This function returns a number of possible values:

  1. CS_BAD_DATA  = -2 is returned if any of the username or passwords are null length strings or do not exist.
  2. CS_BAD_USAGE = -1is returned if an invalid number of parameters is passed to the function.
  3. CS_SUCCESS = 0 is returned if the function successfully authenticated the user with the supplied parameters.
  4. Any other positive integer indicates a PAM error. The meaning of the error value can be determined by referencing the /usr/include/security/_pam_types.h header file.

Sign Off by:

Project Manager

 

  • Log in [5] to post comments

Source URL:https://niedermayer.ca/node/195

Links
[1] https://niedermayer.ca/user/login?destination=node/195%23comment-form [2] https://niedermayer.ca/user/login?destination=node/196%23comment-form [3] https://niedermayer.ca/user/login?destination=node/197%23comment-form [4] https://niedermayer.ca/user/login?destination=node/198%23comment-form [5] https://niedermayer.ca/user/login?destination=node/199%23comment-form