Header And Logo

PostgreSQL
| The world's most advanced open source database.

Defines | Functions | Variables

passwordcheck.c File Reference

#include "postgres.h"
#include <ctype.h>
#include "commands/user.h"
#include "fmgr.h"
#include "libpq/md5.h"
Include dependency graph for passwordcheck.c:

Go to the source code of this file.

Defines

#define MIN_PWD_LENGTH   8

Functions

void _PG_init (void)
static void check_password (const char *username, const char *password, int password_type, Datum validuntil_time, bool validuntil_null)

Variables

 PG_MODULE_MAGIC

Define Documentation

#define MIN_PWD_LENGTH   8

Definition at line 31 of file passwordcheck.c.

Referenced by check_password().


Function Documentation

void _PG_init ( void   ) 

Definition at line 144 of file passwordcheck.c.

References check_password_hook.

{
    /* activate password checks when the module is loaded */
    check_password_hook = check_password;
}

static void check_password ( const char *  username,
const char *  password,
int  password_type,
Datum  validuntil_time,
bool  validuntil_null 
) [static]

Definition at line 53 of file passwordcheck.c.

References elog, ereport, errcode(), errmsg(), ERROR, i, MD5_PASSWD_LEN, MIN_PWD_LENGTH, PASSWORD_TYPE_MD5, PASSWORD_TYPE_PLAINTEXT, and pg_md5_encrypt().

{
    int         namelen = strlen(username);
    int         pwdlen = strlen(password);
    char        encrypted[MD5_PASSWD_LEN + 1];
    int         i;
    bool        pwd_has_letter,
                pwd_has_nonletter;

    switch (password_type)
    {
        case PASSWORD_TYPE_MD5:

            /*
             * Unfortunately we cannot perform exhaustive checks on encrypted
             * passwords - we are restricted to guessing. (Alternatively, we
             * could insist on the password being presented non-encrypted, but
             * that has its own security disadvantages.)
             *
             * We only check for username = password.
             */
            if (!pg_md5_encrypt(username, username, namelen, encrypted))
                elog(ERROR, "password encryption failed");
            if (strcmp(password, encrypted) == 0)
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                         errmsg("password must not contain user name")));
            break;

        case PASSWORD_TYPE_PLAINTEXT:

            /*
             * For unencrypted passwords we can perform better checks
             */

            /* enforce minimum length */
            if (pwdlen < MIN_PWD_LENGTH)
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                         errmsg("password is too short")));

            /* check if the password contains the username */
            if (strstr(password, username))
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                         errmsg("password must not contain user name")));

            /* check if the password contains both letters and non-letters */
            pwd_has_letter = false;
            pwd_has_nonletter = false;
            for (i = 0; i < pwdlen; i++)
            {
                /*
                 * isalpha() does not work for multibyte encodings but let's
                 * consider non-ASCII characters non-letters
                 */
                if (isalpha((unsigned char) password[i]))
                    pwd_has_letter = true;
                else
                    pwd_has_nonletter = true;
            }
            if (!pwd_has_letter || !pwd_has_nonletter)
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                errmsg("password must contain both letters and nonletters")));

#ifdef USE_CRACKLIB
            /* call cracklib to check password */
            if (FascistCheck(password, CRACKLIB_DICTPATH))
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                         errmsg("password is easily cracked")));
#endif
            break;

        default:
            elog(ERROR, "unrecognized password type: %d", password_type);
            break;
    }

    /* all checks passed, password is ok */
}


Variable Documentation

Definition at line 28 of file passwordcheck.c.