Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "postgres.h"
00017
00018 #include <unistd.h>
00019 #ifdef HAVE_CRYPT_H
00020 #include <crypt.h>
00021 #endif
00022
00023 #include "catalog/pg_authid.h"
00024 #include "libpq/crypt.h"
00025 #include "libpq/md5.h"
00026 #include "miscadmin.h"
00027 #include "utils/builtins.h"
00028 #include "utils/syscache.h"
00029 #include "utils/timestamp.h"
00030
00031
00032 int
00033 md5_crypt_verify(const Port *port, const char *role, char *client_pass)
00034 {
00035 int retval = STATUS_ERROR;
00036 char *shadow_pass,
00037 *crypt_pwd;
00038 TimestampTz vuntil = 0;
00039 char *crypt_client_pass = client_pass;
00040 HeapTuple roleTup;
00041 Datum datum;
00042 bool isnull;
00043
00044
00045
00046
00047
00048
00049 ImmediateInterruptOK = false;
00050
00051
00052 roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(role));
00053 if (!HeapTupleIsValid(roleTup))
00054 return STATUS_ERROR;
00055
00056 datum = SysCacheGetAttr(AUTHNAME, roleTup,
00057 Anum_pg_authid_rolpassword, &isnull);
00058 if (isnull)
00059 {
00060 ReleaseSysCache(roleTup);
00061 return STATUS_ERROR;
00062 }
00063 shadow_pass = TextDatumGetCString(datum);
00064
00065 datum = SysCacheGetAttr(AUTHNAME, roleTup,
00066 Anum_pg_authid_rolvaliduntil, &isnull);
00067 if (!isnull)
00068 vuntil = DatumGetTimestampTz(datum);
00069
00070 ReleaseSysCache(roleTup);
00071
00072 if (*shadow_pass == '\0')
00073 return STATUS_ERROR;
00074
00075
00076 ImmediateInterruptOK = true;
00077
00078 CHECK_FOR_INTERRUPTS();
00079
00080
00081
00082
00083
00084 switch (port->hba->auth_method)
00085 {
00086 case uaMD5:
00087 crypt_pwd = palloc(MD5_PASSWD_LEN + 1);
00088 if (isMD5(shadow_pass))
00089 {
00090
00091 if (!pg_md5_encrypt(shadow_pass + strlen("md5"),
00092 port->md5Salt,
00093 sizeof(port->md5Salt), crypt_pwd))
00094 {
00095 pfree(crypt_pwd);
00096 return STATUS_ERROR;
00097 }
00098 }
00099 else
00100 {
00101
00102 char *crypt_pwd2 = palloc(MD5_PASSWD_LEN + 1);
00103
00104 if (!pg_md5_encrypt(shadow_pass,
00105 port->user_name,
00106 strlen(port->user_name),
00107 crypt_pwd2))
00108 {
00109 pfree(crypt_pwd);
00110 pfree(crypt_pwd2);
00111 return STATUS_ERROR;
00112 }
00113 if (!pg_md5_encrypt(crypt_pwd2 + strlen("md5"),
00114 port->md5Salt,
00115 sizeof(port->md5Salt),
00116 crypt_pwd))
00117 {
00118 pfree(crypt_pwd);
00119 pfree(crypt_pwd2);
00120 return STATUS_ERROR;
00121 }
00122 pfree(crypt_pwd2);
00123 }
00124 break;
00125 default:
00126 if (isMD5(shadow_pass))
00127 {
00128
00129 crypt_client_pass = palloc(MD5_PASSWD_LEN + 1);
00130 if (!pg_md5_encrypt(client_pass,
00131 port->user_name,
00132 strlen(port->user_name),
00133 crypt_client_pass))
00134 {
00135 pfree(crypt_client_pass);
00136 return STATUS_ERROR;
00137 }
00138 }
00139 crypt_pwd = shadow_pass;
00140 break;
00141 }
00142
00143 if (strcmp(crypt_client_pass, crypt_pwd) == 0)
00144 {
00145
00146
00147
00148 if (isnull)
00149 retval = STATUS_OK;
00150 else if (vuntil < GetCurrentTimestamp())
00151 retval = STATUS_ERROR;
00152 else
00153 retval = STATUS_OK;
00154 }
00155
00156 if (port->hba->auth_method == uaMD5)
00157 pfree(crypt_pwd);
00158 if (crypt_client_pass != client_pass)
00159 pfree(crypt_client_pass);
00160
00161 return retval;
00162 }