4
4
* Look into pg_user and check the encrypted password with the one
5
5
* passed in from the frontend.
6
6
*
7
+ * Modification History
8
+ *
9
+ * Dec 17, 1997 - Todd A. Brandys
10
+ * Orignal Version Completed.
11
+ *
7
12
*
8
13
*-------------------------------------------------------------------------
9
14
*/
18
23
19
24
#include "postgres.h"
20
25
#include "miscadmin.h"
21
- #include "libpq/crypt.h"
22
26
#include "utils/nabstime.h"
23
- #include "utils/palloc.h"
24
27
#include "storage/fd.h"
28
+ #include "libpq/crypt.h"
29
+
30
+ char * * pwd_cache = NULL ;
31
+ int pwd_cache_count = 0 ;
32
+
33
+ /*-------------------------------------------------------------------------*/
25
34
26
35
char * crypt_getpwdfilename () {
27
36
28
- static char * filename = NULL ;
37
+ static char * pfnam = NULL ;
29
38
30
- if (!filename ) {
31
- filename = (char * )palloc (strlen (DataDir ) + strlen (CRYPT_PWD_FILE ) + 2 );
32
- sprintf (filename , "%s/%s" , DataDir , CRYPT_PWD_FILE );
39
+ if (!pfnam ) {
40
+ pfnam = (char * )malloc (strlen (DataDir ) + strlen (CRYPT_PWD_FILE ) + 2 );
41
+ sprintf (pfnam , "%s/%s" , DataDir , CRYPT_PWD_FILE );
33
42
}
34
43
35
- return filename ;
44
+ return pfnam ;
45
+ }
46
+
47
+ /*-------------------------------------------------------------------------*/
48
+
49
+ char * crypt_getpwdreloadfilename () {
50
+
51
+ static char * rpfnam = NULL ;
52
+
53
+ if (!rpfnam ) {
54
+ char * pwdfilename ;
55
+
56
+ pwdfilename = crypt_getpwdfilename ();
57
+ rpfnam = (char * )malloc (strlen (pwdfilename ) + strlen (CRYPT_PWD_RELOAD_SUFX ) + 1 );
58
+ sprintf (rpfnam , "%s%s" , pwdfilename , CRYPT_PWD_RELOAD_SUFX );
59
+ }
60
+
61
+ return rpfnam ;
36
62
}
37
63
38
64
/*-------------------------------------------------------------------------*/
39
65
40
66
static
41
67
FILE * crypt_openpwdfile () {
42
-
43
68
char * filename ;
69
+ FILE * pwdfile ;
44
70
45
71
filename = crypt_getpwdfilename ();
46
- return (AllocateFile (filename , "r" ));
72
+ pwdfile = AllocateFile (filename , "r" );
73
+
74
+ return pwdfile ;
47
75
}
48
76
49
77
/*-------------------------------------------------------------------------*/
50
78
51
79
static
52
- void crypt_parsepwdfile ( FILE * datafile , char * * login , char * * pwd , char * * valdate ) {
80
+ int compar_user ( const void * user_a , const void * user_b ) {
53
81
54
- char buffer [ 256 ];
55
- char * parse ;
56
- int count ,
57
- i ;
82
+ int min ,
83
+ value ;
84
+ char * login_a ;
85
+ char * login_b ;
58
86
59
- fgets ( buffer , 256 , datafile );
60
- parse = buffer ;
87
+ login_a = * (( char * * ) user_a );
88
+ login_b = * (( char * * ) user_b ) ;
61
89
62
- /* store a copy of user login to return
90
+ /* We only really want to compare the user logins which are first. We look
91
+ * for the first SEPSTR char getting the number of chars there are before it.
92
+ * We only need to compare to the min count from the two strings.
63
93
*/
64
- count = strcspn (parse , "#" );
65
- * login = (char * )palloc (count + 1 );
66
- strncpy (* login , parse , count );
67
- (* login )[count ] = '\0' ;
68
- parse += (count + 1 );
94
+ min = strcspn (login_a , CRYPT_PWD_FILE_SEPSTR );
95
+ value = strcspn (login_b , CRYPT_PWD_FILE_SEPSTR );
96
+ if (value < min )
97
+ min = value ;
98
+
99
+ /* We add one to min so that the separator character is included in the
100
+ * comparison. Why? I believe this will prevent logins that are proper
101
+ * prefixes of other logins from being 'masked out'. Being conservative!
102
+ */
103
+ return strncmp (login_a , login_b , min + 1 );
104
+ }
105
+
106
+ /*-------------------------------------------------------------------------*/
107
+
108
+ static
109
+ void crypt_loadpwdfile () {
110
+
111
+ char * filename ;
112
+ int result ;
113
+ FILE * pwd_file ;
114
+ char buffer [256 ];
115
+
116
+ filename = crypt_getpwdreloadfilename ();
117
+ result = unlink (filename );
118
+
119
+ /* We want to delete the flag file before reading the contents of the pg_pwd
120
+ * file. If result == 0 then the unlink of the reload file was successful.
121
+ * This means that a backend performed a COPY of the pg_user file to
122
+ * pg_pwd. Therefore we must now do a reload.
123
+ */
124
+ if (!pwd_cache || !result ) {
125
+ if (pwd_cache ) { /* free the old data only if this is a reload */
126
+ while (pwd_cache_count -- ) {
127
+ free ((void * )pwd_cache [pwd_cache_count ]);
128
+ }
129
+ free ((void * )pwd_cache );
130
+ pwd_cache = NULL ;
131
+ pwd_cache_count = 0 ;
132
+ }
133
+
134
+ if (!(pwd_file = crypt_openpwdfile ()))
135
+ return ;
136
+
137
+ /* Here is where we load the data from pg_pwd.
138
+ */
139
+ while (fgets (buffer , 256 , pwd_file ) != NULL ) {
140
+ /* We must remove the return char at the end of the string, as this will
141
+ * affect the correct parsing of the password entry.
142
+ */
143
+ if (buffer [(result = strlen (buffer ) - 1 )] == '\n' )
144
+ buffer [result ] = '\0' ;
145
+
146
+ pwd_cache = (char * * )realloc ((void * )pwd_cache , sizeof (char * ) * (pwd_cache_count + 1 ));
147
+ pwd_cache [pwd_cache_count ++ ] = strdup (buffer );
148
+ }
149
+ fclose (pwd_file );
150
+
151
+ /* Now sort the entries in the cache for faster searching later.
152
+ */
153
+ qsort ((void * )pwd_cache , pwd_cache_count , sizeof (char * ), compar_user );
154
+ }
155
+ }
156
+
157
+ /*-------------------------------------------------------------------------*/
158
+
159
+ static
160
+ void crypt_parsepwdentry (char * buffer , char * * pwd , char * * valdate ) {
161
+
162
+ char * parse = buffer ;
163
+ int count ,
164
+ i ;
69
165
70
166
/* skip to the password field
71
167
*/
72
- for (i = 0 ; i < 5 ; i ++ )
73
- parse += (strcspn (parse , "#" ) + 1 );
168
+ for (i = 0 ; i < 6 ; i ++ )
169
+ parse += (strcspn (parse , CRYPT_PWD_FILE_SEPSTR ) + 1 );
74
170
75
171
/* store a copy of user password to return
76
172
*/
77
- count = strcspn (parse , "#" );
78
- * pwd = (char * )palloc (count + 1 );
173
+ count = strcspn (parse , CRYPT_PWD_FILE_SEPSTR );
174
+ * pwd = (char * )malloc (count + 1 );
79
175
strncpy (* pwd , parse , count );
80
176
(* pwd )[count ] = '\0' ;
81
177
parse += (count + 1 );
82
178
83
179
/* store a copy of date login becomes invalid
84
180
*/
85
- count = strcspn (parse , "#" );
86
- * valdate = (char * )palloc (count + 1 );
181
+ count = strcspn (parse , CRYPT_PWD_FILE_SEPSTR );
182
+ * valdate = (char * )malloc (count + 1 );
87
183
strncpy (* valdate , parse , count );
88
184
(* valdate )[count ] = '\0' ;
89
185
parse += (count + 1 );
@@ -92,33 +188,33 @@ void crypt_parsepwdfile(FILE* datafile, char** login, char** pwd, char** valdate
92
188
/*-------------------------------------------------------------------------*/
93
189
94
190
static
95
- void crypt_getloginfo (const char * user , char * * passwd , char * * valuntil ) {
191
+ int crypt_getloginfo (const char * user , char * * passwd , char * * valuntil ) {
96
192
97
- FILE * datafile ;
98
- char * login ;
99
193
char * pwd ;
100
194
char * valdate ;
195
+ void * fakeout ;
101
196
102
197
* passwd = NULL ;
103
198
* valuntil = NULL ;
199
+ crypt_loadpwdfile ();
104
200
105
- if (!(datafile = crypt_openpwdfile ()))
106
- return ;
201
+ if (pwd_cache ) {
202
+ char * * pwd_entry ;
203
+ char user_search [NAMEDATALEN + 2 ];
107
204
108
- while (! feof ( datafile )) {
109
- crypt_parsepwdfile ( datafile , & login , & pwd , & valdate ) ;
110
- if (! strcmp ( login , user )) {
111
- pfree (( void * ) login );
205
+ sprintf ( user_search , "%s\t" , user );
206
+ fakeout = ( void * ) & user_search ;
207
+ if (( pwd_entry = ( char * * ) bsearch (( void * ) & fakeout , ( void * ) pwd_cache , pwd_cache_count , sizeof ( char * ), compar_user ) )) {
208
+ crypt_parsepwdentry ( * pwd_entry , & pwd , & valdate );
112
209
* passwd = pwd ;
113
210
* valuntil = valdate ;
114
- fclose (datafile );
115
- return ;
211
+ return STATUS_OK ;
116
212
}
117
- pfree ((void * )login );
118
- pfree ((void * )pwd );
119
- pfree ((void * )valdate );
213
+
214
+ return STATUS_OK ;
120
215
}
121
- fclose (datafile );
216
+
217
+ return STATUS_ERROR ;
122
218
}
123
219
124
220
/*-------------------------------------------------------------------------*/
@@ -128,16 +224,17 @@ MsgType crypt_salt(const char* user) {
128
224
char * passwd ;
129
225
char * valuntil ;
130
226
131
- crypt_getloginfo (user , & passwd , & valuntil );
227
+ if (crypt_getloginfo (user , & passwd , & valuntil ) == STATUS_ERROR )
228
+ return STARTUP_UNSALT_MSG ;
132
229
133
230
if (passwd == NULL || * passwd == '\0' || !strcmp (passwd , "\\N" )) {
134
- if (passwd ) pfree ((void * )passwd );
135
- if (valuntil ) pfree ((void * )valuntil );
231
+ if (passwd ) free ((void * )passwd );
232
+ if (valuntil ) free ((void * )valuntil );
136
233
return STARTUP_UNSALT_MSG ;
137
234
}
138
235
139
- pfree ((void * )passwd );
140
- if (valuntil ) pfree ((void * )valuntil );
236
+ free ((void * )passwd );
237
+ if (valuntil ) free ((void * )valuntil );
141
238
return STARTUP_SALT_MSG ;
142
239
}
143
240
@@ -152,11 +249,12 @@ int crypt_verify(Port* port, const char* user, const char* pgpass) {
152
249
AbsoluteTime vuntil ,
153
250
current ;
154
251
155
- crypt_getloginfo (user , & passwd , & valuntil );
252
+ if (crypt_getloginfo (user , & passwd , & valuntil ) == STATUS_ERROR )
253
+ return STATUS_ERROR ;
156
254
157
255
if (passwd == NULL || * passwd == '\0' ) {
158
- if (passwd ) pfree ((void * )passwd );
159
- if (valuntil ) pfree ((void * )valuntil );
256
+ if (passwd ) free ((void * )passwd );
257
+ if (valuntil ) free ((void * )valuntil );
160
258
return STATUS_ERROR ;
161
259
}
162
260
@@ -175,8 +273,8 @@ int crypt_verify(Port* port, const char* user, const char* pgpass) {
175
273
retval = STATUS_OK ;
176
274
}
177
275
178
- pfree ((void * )passwd );
179
- if (valuntil ) pfree ((void * )valuntil );
276
+ free ((void * )passwd );
277
+ if (valuntil ) free ((void * )valuntil );
180
278
181
279
return retval ;
182
280
}
0 commit comments