PostgreSQL Source Code  git master
passwordcheck.c File Reference
#include "postgres.h"
#include <ctype.h>
#include "commands/user.h"
#include "fmgr.h"
#include "libpq/crypt.h"
Include dependency graph for passwordcheck.c:

Go to the source code of this file.

Macros

#define MIN_PWD_LENGTH   8
 

Functions

void _PG_init (void)
 
void _PG_fini (void)
 
static void check_password (const char *username, const char *shadow_pass, PasswordType password_type, Datum validuntil_time, bool validuntil_null)
 

Variables

 PG_MODULE_MAGIC
 
static check_password_hook_type prev_check_password_hook = NULL
 

Macro Definition Documentation

◆ MIN_PWD_LENGTH

#define MIN_PWD_LENGTH   8

Definition at line 33 of file passwordcheck.c.

Referenced by check_password().

Function Documentation

◆ _PG_fini()

void _PG_fini ( void  )

Definition at line 153 of file passwordcheck.c.

References check_password_hook, and prev_check_password_hook.

154 {
155  /* uninstall hook */
157 }
static check_password_hook_type prev_check_password_hook
Definition: passwordcheck.c:30
check_password_hook_type check_password_hook
Definition: user.c:49

◆ _PG_init()

void _PG_init ( void  )

Definition at line 142 of file passwordcheck.c.

References check_password(), check_password_hook, and prev_check_password_hook.

143 {
144  /* activate password checks when the module is loaded */
147 }
static check_password_hook_type prev_check_password_hook
Definition: passwordcheck.c:30
static void check_password(const char *username, const char *shadow_pass, PasswordType password_type, Datum validuntil_time, bool validuntil_null)
Definition: passwordcheck.c:56
check_password_hook_type check_password_hook
Definition: user.c:49

◆ check_password()

static void check_password ( const char *  username,
const char *  shadow_pass,
PasswordType  password_type,
Datum  validuntil_time,
bool  validuntil_null 
)
static

Definition at line 56 of file passwordcheck.c.

References ereport, errcode(), errmsg(), ERROR, i, MIN_PWD_LENGTH, password, PASSWORD_TYPE_PLAINTEXT, plain_crypt_verify(), prev_check_password_hook, and STATUS_OK.

Referenced by _PG_init().

61 {
64  password_type, validuntil_time,
65  validuntil_null);
66 
67  if (password_type != PASSWORD_TYPE_PLAINTEXT)
68  {
69  /*
70  * Unfortunately we cannot perform exhaustive checks on encrypted
71  * passwords - we are restricted to guessing. (Alternatively, we could
72  * insist on the password being presented non-encrypted, but that has
73  * its own security disadvantages.)
74  *
75  * We only check for username = password.
76  */
77  char *logdetail;
78 
79  if (plain_crypt_verify(username, shadow_pass, username, &logdetail) == STATUS_OK)
80  ereport(ERROR,
81  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
82  errmsg("password must not equal user name")));
83  }
84  else
85  {
86  /*
87  * For unencrypted passwords we can perform better checks
88  */
89  const char *password = shadow_pass;
90  int pwdlen = strlen(password);
91  int i;
92  bool pwd_has_letter,
93  pwd_has_nonletter;
94 
95  /* enforce minimum length */
96  if (pwdlen < MIN_PWD_LENGTH)
97  ereport(ERROR,
98  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
99  errmsg("password is too short")));
100 
101  /* check if the password contains the username */
102  if (strstr(password, username))
103  ereport(ERROR,
104  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
105  errmsg("password must not contain user name")));
106 
107  /* check if the password contains both letters and non-letters */
108  pwd_has_letter = false;
109  pwd_has_nonletter = false;
110  for (i = 0; i < pwdlen; i++)
111  {
112  /*
113  * isalpha() does not work for multibyte encodings but let's
114  * consider non-ASCII characters non-letters
115  */
116  if (isalpha((unsigned char) password[i]))
117  pwd_has_letter = true;
118  else
119  pwd_has_nonletter = true;
120  }
121  if (!pwd_has_letter || !pwd_has_nonletter)
122  ereport(ERROR,
123  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
124  errmsg("password must contain both letters and nonletters")));
125 
126 #ifdef USE_CRACKLIB
127  /* call cracklib to check password */
128  if (FascistCheck(password, CRACKLIB_DICTPATH))
129  ereport(ERROR,
130  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
131  errmsg("password is easily cracked")));
132 #endif
133  }
134 
135  /* all checks passed, password is ok */
136 }
static char password[100]
Definition: streamutil.c:53
static check_password_hook_type prev_check_password_hook
Definition: passwordcheck.c:30
int plain_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, char **logdetail)
Definition: crypt.c:222
int errcode(int sqlerrcode)
Definition: elog.c:608
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
#define STATUS_OK
Definition: c.h:1120
static char * username
Definition: initdb.c:133
int errmsg(const char *fmt,...)
Definition: elog.c:822
int i
#define MIN_PWD_LENGTH
Definition: passwordcheck.c:33

Variable Documentation

◆ PG_MODULE_MAGIC

PG_MODULE_MAGIC

Definition at line 27 of file passwordcheck.c.

◆ prev_check_password_hook

check_password_hook_type prev_check_password_hook = NULL
static

Definition at line 30 of file passwordcheck.c.

Referenced by _PG_fini(), _PG_init(), and check_password().