Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3c1332e

Browse files
committed
Slightly delayed patches from Todd...damn holidays :)
o A new patch that contains the following changes: -- The pg_pwd file is now cached in the postmaster's memory. -- pg_pwd is reloaded when the postmaster detects a flag file creat()'ed by a backend. -- qsort() is used to sort loaded password entries, and bsearch() is is used to find entries in the pg_pwd cache. -- backends now copy the pg_user relation to pg_pwd.pid, and then rename the temp file to be pg_pwd. -- The delimiter for pg_pwd has been changed to a tab character.
1 parenta544b60 commit3c1332e

File tree

4 files changed

+191
-62
lines changed

4 files changed

+191
-62
lines changed

‎src/backend/commands/user.c‎

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
*/
1212
#include<stdio.h>/* for sprintf() */
1313
#include<string.h>
14+
#include<sys/types.h>
15+
#include<sys/stat.h>
16+
#include<fcntl.h>
17+
#include<unistd.h>
1418

1519
#include<postgres.h>
1620

@@ -25,7 +29,6 @@
2529
#include<storage/lmgr.h>
2630
#include<tcop/tcopprot.h>
2731
#include<utils/acl.h>
28-
#include<utils/palloc.h>
2932
#include<utils/rel.h>
3033
#include<commands/user.h>
3134

@@ -40,10 +43,31 @@ static
4043
voidUpdatePgPwdFile(char*sql) {
4144

4245
char*filename;
46+
char*tempname;
4347

48+
/* Create a temporary filename to be renamed later. This prevents the
49+
* backend from clobbering the pg_pwd file while the postmaster might be
50+
* reading from it.
51+
*/
4452
filename=crypt_getpwdfilename();
45-
sprintf(sql,"copy %s to '%s' using delimiters '#'",UserRelationName,filename);
53+
tempname= (char*)malloc(strlen(filename)+12);
54+
sprintf(tempname,"%s.%d",filename,getpid());
55+
56+
/* Copy the contents of pg_user to the pg_pwd ASCII file using a the SEPCHAR
57+
* character as the delimiter between fields. Then rename the file to its
58+
* final name.
59+
*/
60+
sprintf(sql,"copy %s to '%s' using delimiters %s",UserRelationName,tempname,CRYPT_PWD_FILE_SEPCHAR);
4661
pg_exec_query(sql, (char**)NULL, (Oid*)NULL,0);
62+
rename(tempname,filename);
63+
free((void*)tempname);
64+
65+
/* Create a flag file the postmaster will detect the next time it tries to
66+
* authenticate a user. The postmaster will know to reload the pg_pwd file
67+
* contents.
68+
*/
69+
filename=crypt_getpwdreloadfilename();
70+
creat(filename,S_IRUSR |S_IWUSR);
4771
}
4872

4973
/*---------------------------------------------------------------------
@@ -283,7 +307,7 @@ extern void RemoveUser(char* user) {
283307
HeapTupletuple;
284308
Datumdatum;
285309
Bufferbuffer;
286-
charsql[256];
310+
charsql[512];
287311
booln,
288312
inblock;
289313
intusesysid=-1,
@@ -348,8 +372,8 @@ extern void RemoveUser(char* user) {
348372
if ((int)datum==usesysid) {
349373
datum=heap_getattr(tuple,buffer,Anum_pg_database_datname,pg_dsc,&n);
350374
if (memcmp((void*)datum,"template1",9)) {
351-
dbase= (char**)repalloc((void*)dbase,sizeof(char*)* (ndbase+1));
352-
dbase[ndbase]= (char*)palloc(NAMEDATALEN+1);
375+
dbase= (char**)realloc((void*)dbase,sizeof(char*)* (ndbase+1));
376+
dbase[ndbase]= (char*)malloc(NAMEDATALEN+1);
353377
memcpy((void*)dbase[ndbase], (void*)datum,NAMEDATALEN);
354378
dbase[ndbase++][NAMEDATALEN]='\0';
355379
}
@@ -362,11 +386,11 @@ extern void RemoveUser(char* user) {
362386
while (ndbase--) {
363387
elog(NOTICE,"Dropping database %s",dbase[ndbase]);
364388
sprintf(sql,"drop database %s",dbase[ndbase]);
365-
pfree((void*)dbase[ndbase]);
389+
free((void*)dbase[ndbase]);
366390
pg_exec_query(sql, (char**)NULL, (Oid*)NULL,0);
367391
}
368392
if (dbase)
369-
pfree((void*)dbase);
393+
free((void*)dbase);
370394

371395
/* Since pg_user is global over all databases, one of two things must be done
372396
* to insure complete consistency. First, pg_user could be made non-global.

‎src/backend/libpq/crypt.c‎

Lines changed: 151 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
* Look into pg_user and check the encrypted password with the one
55
* passed in from the frontend.
66
*
7+
* Modification History
8+
*
9+
* Dec 17, 1997 - Todd A. Brandys
10+
*Orignal Version Completed.
11+
*
712
*
813
*-------------------------------------------------------------------------
914
*/
@@ -18,72 +23,163 @@
1823

1924
#include"postgres.h"
2025
#include"miscadmin.h"
21-
#include"libpq/crypt.h"
2226
#include"utils/nabstime.h"
23-
#include"utils/palloc.h"
2427
#include"storage/fd.h"
28+
#include"libpq/crypt.h"
29+
30+
char**pwd_cache=NULL;
31+
intpwd_cache_count=0;
32+
33+
/*-------------------------------------------------------------------------*/
2534

2635
char*crypt_getpwdfilename() {
2736

28-
staticchar*filename=NULL;
37+
staticchar*pfnam=NULL;
2938

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);
3342
}
3443

35-
returnfilename;
44+
returnpfnam;
45+
}
46+
47+
/*-------------------------------------------------------------------------*/
48+
49+
char*crypt_getpwdreloadfilename() {
50+
51+
staticchar*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+
returnrpfnam;
3662
}
3763

3864
/*-------------------------------------------------------------------------*/
3965

4066
static
4167
FILE*crypt_openpwdfile() {
42-
4368
char*filename;
69+
FILE*pwdfile;
4470

4571
filename=crypt_getpwdfilename();
46-
return (AllocateFile(filename,"r"));
72+
pwdfile=AllocateFile(filename,"r");
73+
74+
returnpwdfile;
4775
}
4876

4977
/*-------------------------------------------------------------------------*/
5078

5179
static
52-
voidcrypt_parsepwdfile(FILE*datafile,char**login,char**pwd,char**valdate) {
80+
intcompar_user(constvoid*user_a,constvoid*user_b) {
5381

54-
charbuffer[256];
55-
char*parse;
56-
intcount,
57-
i;
82+
intmin,
83+
value;
84+
char*login_a;
85+
char*login_b;
5886

59-
fgets(buffer,256,datafile);
60-
parse=buffer;
87+
login_a=*((char**)user_a);
88+
login_b=*((char**)user_b);
6189

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.
6393
*/
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+
returnstrncmp(login_a,login_b,min+1);
104+
}
105+
106+
/*-------------------------------------------------------------------------*/
107+
108+
static
109+
voidcrypt_loadpwdfile() {
110+
111+
char*filename;
112+
intresult;
113+
FILE*pwd_file;
114+
charbuffer[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+
voidcrypt_parsepwdentry(char*buffer,char**pwd,char**valdate) {
161+
162+
char*parse=buffer;
163+
intcount,
164+
i;
69165

70166
/* skip to the password field
71167
*/
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);
74170

75171
/* store a copy of user password to return
76172
*/
77-
count=strcspn(parse,"#");
78-
*pwd= (char*)palloc(count+1);
173+
count=strcspn(parse,CRYPT_PWD_FILE_SEPSTR);
174+
*pwd= (char*)malloc(count+1);
79175
strncpy(*pwd,parse,count);
80176
(*pwd)[count]='\0';
81177
parse+= (count+1);
82178

83179
/* store a copy of date login becomes invalid
84180
*/
85-
count=strcspn(parse,"#");
86-
*valdate= (char*)palloc(count+1);
181+
count=strcspn(parse,CRYPT_PWD_FILE_SEPSTR);
182+
*valdate= (char*)malloc(count+1);
87183
strncpy(*valdate,parse,count);
88184
(*valdate)[count]='\0';
89185
parse+= (count+1);
@@ -92,33 +188,33 @@ void crypt_parsepwdfile(FILE* datafile, char** login, char** pwd, char** valdate
92188
/*-------------------------------------------------------------------------*/
93189

94190
static
95-
voidcrypt_getloginfo(constchar*user,char**passwd,char**valuntil) {
191+
intcrypt_getloginfo(constchar*user,char**passwd,char**valuntil) {
96192

97-
FILE*datafile;
98-
char*login;
99193
char*pwd;
100194
char*valdate;
195+
void*fakeout;
101196

102197
*passwd=NULL;
103198
*valuntil=NULL;
199+
crypt_loadpwdfile();
104200

105-
if (!(datafile=crypt_openpwdfile()))
106-
return;
201+
if (pwd_cache) {
202+
char**pwd_entry;
203+
charuser_search[NAMEDATALEN+2];
107204

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);
112209
*passwd=pwd;
113210
*valuntil=valdate;
114-
fclose(datafile);
115-
return;
211+
returnSTATUS_OK;
116212
}
117-
pfree((void*)login);
118-
pfree((void*)pwd);
119-
pfree((void*)valdate);
213+
214+
returnSTATUS_OK;
120215
}
121-
fclose(datafile);
216+
217+
returnSTATUS_ERROR;
122218
}
123219

124220
/*-------------------------------------------------------------------------*/
@@ -128,16 +224,17 @@ MsgType crypt_salt(const char* user) {
128224
char*passwd;
129225
char*valuntil;
130226

131-
crypt_getloginfo(user,&passwd,&valuntil);
227+
if (crypt_getloginfo(user,&passwd,&valuntil)==STATUS_ERROR)
228+
returnSTARTUP_UNSALT_MSG;
132229

133230
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);
136233
returnSTARTUP_UNSALT_MSG;
137234
}
138235

139-
pfree((void*)passwd);
140-
if (valuntil)pfree((void*)valuntil);
236+
free((void*)passwd);
237+
if (valuntil)free((void*)valuntil);
141238
returnSTARTUP_SALT_MSG;
142239
}
143240

@@ -152,11 +249,12 @@ int crypt_verify(Port* port, const char* user, const char* pgpass) {
152249
AbsoluteTimevuntil,
153250
current;
154251

155-
crypt_getloginfo(user,&passwd,&valuntil);
252+
if (crypt_getloginfo(user,&passwd,&valuntil)==STATUS_ERROR)
253+
returnSTATUS_ERROR;
156254

157255
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);
160258
returnSTATUS_ERROR;
161259
}
162260

@@ -175,8 +273,8 @@ int crypt_verify(Port* port, const char* user, const char* pgpass) {
175273
retval=STATUS_OK;
176274
}
177275

178-
pfree((void*)passwd);
179-
if (valuntil)pfree((void*)valuntil);
276+
free((void*)passwd);
277+
if (valuntil)free((void*)valuntil);
180278

181279
returnretval;
182280
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp