14
14
#include <stdlib.h>
15
15
#include <unistd.h>
18
19
#include "pam_pgsql.h"
19
20
#include "pam_pgsql_options.h"
22
read_config_file(modopt_t *options)
29
if(access(options->fileconf, R_OK) == 0) {
31
fp = fopen(options->fileconf, "r");
33
if(fp == NULL) return;
35
while(fgets(buffer, 1024, fp)) {
37
if((eq = strchr(buffer, '='))) {
40
while(end > buffer && isspace(*end)) end--;
44
while(*val && isspace(*val)) val++;
47
while(*eq != '\0') eq++;
58
if(!strcmp(buffer, "auth_query")) {
59
options->query_auth = strdup(val);
60
} else if( strcmp(buffer, "connect") == 0 ) {
23
read_config_file(modopt_t *options) {
29
fp = fopen(options->fileconf, "r");
30
if (errno == EACCES) {
31
SYSLOG("no access for config file");
33
if (fp == NULL) return;
35
while(fgets(buffer, 1024, fp)) {
37
if((eq = strchr(buffer, '='))) {
40
while(end > buffer && isspace(*end)) end--;
44
while(*val && isspace(*val)) val++;
47
while(*eq != '\0') eq++;
56
if(!strcmp(buffer, "auth_query")) {
57
options->query_auth = strdup(val);
58
} else if( strcmp(buffer, "connect") == 0 ) {
61
59
options->connstr = strdup(val);
62
} else if(!strcmp(buffer, "auth_succ_query")) {
63
options->query_auth_succ = strdup(val);
64
} else if(!strcmp(buffer, "auth_fail_query")) {
65
options->query_auth_fail = strdup(val);
66
} else if(!strcmp(buffer, "acct_query")) {
67
options->query_acct = strdup(val);
68
} else if(!strcmp(buffer, "pwd_query")) {
69
options->query_pwd = strdup(val);
70
} else if(!strcmp(buffer, "session_open_query")) {
71
options->query_session_open = strdup(val);
72
} else if(!strcmp(buffer, "session_close_query")) {
73
options->query_session_close = strdup(val);
74
} else if(!strcmp(buffer, "database")) {
75
options->db = strdup(val);
76
} else if(!strcmp(buffer, "table")) {
77
options->table = strdup(val);
78
} else if(!strcmp(buffer, "host")) {
79
options->host = strdup(val);
80
} else if(!strcmp(buffer, "port")) {
81
options->port = strdup(val);
82
} else if(!strcmp(buffer, "timeout")) {
83
options->timeout = strdup(val);
84
} else if(!strcmp(buffer, "user")) {
85
options->user = strdup(val);
86
} else if(!strcmp(buffer, "sslmode")) {
88
/* If not a valid option */
89
if(strcmp(val, "require") != 0 && strcmp(val, "prefer") != 0 && strcmp(val, "allow") != 0 && strcmp(val,"disable") != 0) {
90
SYSLOG("sslmode \"%s\" is not a valid option! Falling back to \"prefer\".", val);
91
options->sslmode = strdup("prefer");
93
options->sslmode = strdup(val);
95
} else if(!strcmp(buffer, "password")) {
96
options->passwd = strdup(val);
97
} else if(!strcmp(buffer, "user_column")) {
98
options->column_user = strdup(val);
99
} else if(!strcmp(buffer, "pwd_column")) {
100
options->column_pwd = strdup(val);
101
} else if(!strcmp(buffer, "expired_column")) {
102
options->column_expired = strdup(val);
103
} else if(!strcmp(buffer, "newtok_column")) {
104
options->column_newpwd = strdup(val);
105
} else if(!strcmp(buffer, "pw_type")) {
106
options->pw_type = PW_CLEAR;
107
if(!strcmp(val, "md5")) {
108
options->pw_type = PW_MD5;
109
} else if(!strcmp(val, "sha1")) {
110
options->pw_type = PW_SHA1;
111
} else if(!strcmp(val, "crypt")) {
112
options->pw_type = PW_CRYPT;
113
} else if(!strcmp(val, "crypt_md5")) {
114
options->pw_type = PW_CRYPT_MD5;
115
} else if(!strcmp(val, "md5_postgres")) {
116
options->pw_type = PW_MD5_POSTGRES;
118
} else if(!strcmp(buffer, "debug")) {
127
SYSLOG("no access for config file");
60
} else if(!strcmp(buffer, "auth_succ_query")) {
61
options->query_auth_succ = strdup(val);
62
} else if(!strcmp(buffer, "auth_fail_query")) {
63
options->query_auth_fail = strdup(val);
64
} else if(!strcmp(buffer, "acct_query")) {
65
options->query_acct = strdup(val);
66
} else if(!strcmp(buffer, "pwd_query")) {
67
options->query_pwd = strdup(val);
68
} else if(!strcmp(buffer, "session_open_query")) {
69
options->query_session_open = strdup(val);
70
} else if(!strcmp(buffer, "session_close_query")) {
71
options->query_session_close = strdup(val);
72
} else if(!strcmp(buffer, "database")) {
73
options->db = strdup(val);
74
} else if(!strcmp(buffer, "table")) {
75
options->table = strdup(val);
76
} else if(!strcmp(buffer, "host")) {
77
options->host = strdup(val);
78
} else if(!strcmp(buffer, "port")) {
79
options->port = strdup(val);
80
} else if(!strcmp(buffer, "timeout")) {
81
options->timeout = strdup(val);
82
} else if(!strcmp(buffer, "user")) {
83
options->user = strdup(val);
84
} else if(!strcmp(buffer, "sslmode")) {
86
/* If not a valid option */
87
if(strcmp(val, "require") != 0 && strcmp(val, "prefer") != 0 && strcmp(val, "allow") != 0 && strcmp(val,"disable") != 0) {
88
SYSLOG("sslmode \"%s\" is not a valid option! Falling back to \"prefer\".", val);
89
options->sslmode = strdup("prefer");
91
options->sslmode = strdup(val);
92
} else if(!strcmp(buffer, "password")) {
93
options->passwd = strdup(val);
94
} else if(!strcmp(buffer, "user_column")) {
95
options->column_user = strdup(val);
96
} else if(!strcmp(buffer, "pwd_column")) {
97
options->column_pwd = strdup(val);
98
} else if(!strcmp(buffer, "expired_column")) {
99
options->column_expired = strdup(val);
100
} else if(!strcmp(buffer, "newtok_column")) {
101
options->column_newpwd = strdup(val);
102
} else if(!strcmp(buffer, "pw_type")) {
103
options->pw_type = PW_CLEAR;
104
if(!strcmp(val, "md5")) {
105
options->pw_type = PW_MD5;
106
} else if(!strcmp(val, "sha1")) {
107
options->pw_type = PW_SHA1;
108
} else if(!strcmp(val, "crypt")) {
109
options->pw_type = PW_CRYPT;
110
} else if(!strcmp(val, "crypt_md5")) {
111
options->pw_type = PW_CRYPT_MD5;
112
} else if(!strcmp(val, "md5_postgres")) {
113
options->pw_type = PW_MD5_POSTGRES;
115
} else if(!strcmp(buffer, "debug")) {
133
126
modopt_t * mod_options(int argc, const char **argv) {
137
modopt_t * modopt = (modopt_t *)malloc(sizeof(modopt_t));
143
static const struct opttab std_options[] = {
144
{ "debug", PAM_OPT_DEBUG },
145
{ "no_warn", PAM_OPT_NO_WARN },
146
{ "authtok", PAM_OPT_USE_FIRST_PASS },
147
{ "use_authtok", PAM_OPT_USE_FIRST_PASS },
148
{ "use_first_pass", PAM_OPT_USE_FIRST_PASS },
149
{ "try_first_pass", PAM_OPT_TRY_FIRST_PASS },
150
{ "use_mapped_pass",PAM_OPT_USE_MAPPED_PASS },
151
{ "echo_pass", PAM_OPT_ECHO_PASS },
154
const struct opttab *p;
156
/* Initializing values */
157
modopt->connstr = NULL;
161
modopt->table = NULL;
162
modopt->passwd = NULL;
163
modopt->pw_type = PW_SHA1;
164
modopt->sslmode = strdup("prefer");
165
modopt->timeout = NULL;
166
modopt->fileconf = NULL;
167
modopt->column_pwd = NULL;
168
modopt->column_user = NULL;
169
modopt->column_expired = NULL;
170
modopt->column_newpwd = NULL;
171
modopt->query_acct = NULL;
172
modopt->query_pwd = NULL;
173
modopt->query_auth = NULL;
174
modopt->query_auth_succ = NULL;
175
modopt->query_auth_fail = NULL;
176
modopt->query_session_open = NULL;
177
modopt->query_session_close = NULL;
178
modopt->port = strdup("5432");
180
modopt->std_flags = 0;
182
for(i=0;i<argc;i++) {
184
for (p = std_options; p->name[0] != '\0'; p++) {
185
if (strcmp(argv[i], p->name) == 0) {
186
modopt->std_flags |= p->value;
191
ptr = strchr(argv[i], '=');
195
option = strndup(argv[i], ptr-argv[i]);
196
value = strndup(ptr+1, strchr(argv[i],'\0')-ptr);
198
if( strcmp(option, "host") == 0 ) {
199
modopt->host = strdup(value);
200
} else if( strcmp(option, "config_file") == 0 ) {
201
modopt->fileconf = strdup(value);
202
} else if( strcmp(option, "database") == 0 ) {
203
modopt->db = strdup(value);
204
} else if( strcmp(option, "table") == 0 ) {
205
modopt->table = strdup(value);
206
} else if( strcmp(option, "user") == 0 ) {
207
modopt->user = strdup(value);
208
} else if( strcmp(option, "password") == 0 ) {
209
modopt->passwd = strdup(value);
210
} else if( strcmp(option, "sslmode") == 0 ) {
212
/* If not a valid option */
213
if(strcmp(value, "require") != 0 && strcmp(value, "prefer") != 0 && strcmp(value, "allow") != 0 && strcmp(value,"disable") != 0) {
214
SYSLOG("sslmode \"%s\" is not a valid option! Falling back to \"prefer\".", value);
215
modopt->sslmode = strdup("prefer");
217
modopt->sslmode = strdup(value);
219
} else if( strcmp(option, "debug") == 0 ) {
220
modopt->debug = atoi(value);
221
} else if( strcmp(option, "port") == 0 ) {
222
modopt->port = strdup(value);
227
if( strcmp(argv[i], "fileconf") == 0 ) {
228
modopt->fileconf = strdup(PAM_PGSQL_FILECONF);
229
} else if( strcmp(argv[i], "force") == 0 ) {
237
/* Setting password in the module options is unsafe */
238
if(force == 0 && modopt->passwd != NULL) {
239
SYSLOG("You cannot set the password in the module options, it's unsafe! If you know what you're doing use \"force\" in the options.");
240
free(modopt->passwd);
241
modopt->passwd = NULL;
244
if(modopt->fileconf == NULL)
245
modopt->fileconf = strdup(PAM_PGSQL_FILECONF);
247
read_config_file(modopt);
250
* If the required queries are no given by the user
251
* we create a default one based the given table and columns
253
if(modopt->query_auth == NULL) {
255
if(modopt->column_pwd != NULL && modopt->table != NULL && modopt->column_user != NULL) {
257
modopt->query_auth = (char *) malloc(32+strlen(modopt->column_pwd)+strlen(modopt->table)+strlen(modopt->column_user));
258
sprintf(modopt->query_auth, "select %s from %s where %s = %%u", modopt->column_pwd, modopt->table, modopt->column_user);
261
else SYSLOG("Can't build auth query");
265
if(modopt->query_acct == NULL) {
267
if(modopt->column_expired != NULL && modopt->column_pwd != NULL && modopt->column_newpwd != NULL && modopt->table != NULL && modopt->column_user != NULL) {
269
modopt->query_acct = (char *) malloc(96+2*strlen(modopt->column_pwd)+strlen(modopt->table)+strlen(modopt->column_user)+2*strlen(modopt->column_expired)+2*strlen(modopt->column_newpwd));
270
sprintf(modopt->query_acct, "select (%s = 'y' OR %s = '1'), (%s = 'y' OR %s = '1'), (%s IS NULL OR %s = '') from %s where %s = %%u", modopt->column_expired, modopt->column_expired, modopt->column_newpwd, modopt->column_newpwd, modopt->column_pwd, modopt->column_pwd, modopt->table, modopt->column_user);
272
/* Expired column is null */
273
} else if(modopt->column_pwd != NULL && modopt->column_newpwd != NULL && modopt->table != NULL && modopt->column_user != NULL) {
275
modopt->query_acct = (char *) malloc(96+2*strlen(modopt->column_pwd)+strlen(modopt->table)+strlen(modopt->column_user)+2*strlen(modopt->column_newpwd));
276
sprintf(modopt->query_acct, "select false, (%s = 'y' OR %s = '1'), (%s IS NULL OR %s = '') from %s where %s = %%u", modopt->column_newpwd, modopt->column_newpwd, modopt->column_pwd, modopt->column_pwd, modopt->table, modopt->column_user);
278
/* Newpwd column is null */
279
} else if(modopt->column_expired != NULL && modopt->column_pwd != NULL && modopt->table != NULL && modopt->column_user != NULL) {
281
modopt->query_acct = (char *) malloc(96+2*strlen(modopt->column_pwd)+strlen(modopt->table)+strlen(modopt->column_user)+2*strlen(modopt->column_expired));
282
sprintf(modopt->query_acct, "select (%s = 'y' OR %s = '1'), false, (%s IS NULL OR %s = '') from %s where %s = %%u", modopt->column_newpwd, modopt->column_newpwd, modopt->column_pwd, modopt->column_pwd, modopt->table, modopt->column_user);
288
if(modopt->query_pwd == NULL) {
290
if(modopt->column_pwd != NULL && modopt->table != NULL && modopt->column_user != NULL) {
292
modopt->query_pwd = (char *) malloc(40+strlen(modopt->column_pwd)+strlen(modopt->table)+strlen(modopt->column_user));
293
sprintf(modopt->query_pwd, "update %s set %s = %%p where %s = %%u", modopt->table, modopt->column_pwd, modopt->column_user);
130
modopt_t * modopt = (modopt_t *)malloc(sizeof(modopt_t));
136
static const struct opttab std_options[] = {
137
{ "debug", PAM_OPT_DEBUG },
138
{ "no_warn", PAM_OPT_NO_WARN },
139
{ "authtok", PAM_OPT_USE_FIRST_PASS },
140
{ "use_authtok", PAM_OPT_USE_FIRST_PASS },
141
{ "use_first_pass", PAM_OPT_USE_FIRST_PASS },
142
{ "try_first_pass", PAM_OPT_TRY_FIRST_PASS },
143
{ "use_mapped_pass",PAM_OPT_USE_MAPPED_PASS },
144
{ "echo_pass", PAM_OPT_ECHO_PASS },
147
const struct opttab *p;
149
/* Initializing values */
150
modopt->connstr = NULL;
154
modopt->table = NULL;
155
modopt->passwd = NULL;
156
modopt->pw_type = PW_SHA1;
157
modopt->sslmode = strdup("prefer");
158
modopt->timeout = NULL;
159
modopt->fileconf = NULL;
160
modopt->column_pwd = NULL;
161
modopt->column_user = NULL;
162
modopt->column_expired = NULL;
163
modopt->column_newpwd = NULL;
164
modopt->query_acct = NULL;
165
modopt->query_pwd = NULL;
166
modopt->query_auth = NULL;
167
modopt->query_auth_succ = NULL;
168
modopt->query_auth_fail = NULL;
169
modopt->query_session_open = NULL;
170
modopt->query_session_close = NULL;
171
modopt->port = strdup("5432");
173
modopt->std_flags = 0;
175
for(i=0; i<argc; i++) {
177
for (p = std_options; p->name[0] != '\0'; p++) {
178
if (strcmp(argv[i], p->name) == 0) {
179
modopt->std_flags |= p->value;
184
ptr = strchr(argv[i], '=');
188
option = strndup(argv[i], ptr-argv[i]);
189
value = strndup(ptr+1, strchr(argv[i],'\0')-ptr);
191
if( strcmp(option, "host") == 0 ) {
192
modopt->host = strdup(value);
193
} else if( strcmp(option, "config_file") == 0 ) {
194
modopt->fileconf = strdup(value);
195
} else if( strcmp(option, "database") == 0 ) {
196
modopt->db = strdup(value);
197
} else if( strcmp(option, "table") == 0 ) {
198
modopt->table = strdup(value);
199
} else if( strcmp(option, "user") == 0 ) {
200
modopt->user = strdup(value);
201
} else if( strcmp(option, "password") == 0 ) {
202
modopt->passwd = strdup(value);
203
} else if( strcmp(option, "sslmode") == 0 ) {
205
/* If not a valid option */
206
if(strcmp(value, "require") != 0 && strcmp(value, "prefer") != 0 && strcmp(value, "allow") != 0 && strcmp(value,"disable") != 0) {
207
SYSLOG("sslmode \"%s\" is not a valid option! Falling back to \"prefer\".", value);
208
modopt->sslmode = strdup("prefer");
210
modopt->sslmode = strdup(value);
212
} else if( strcmp(option, "debug") == 0 ) {
213
modopt->debug = atoi(value);
214
} else if( strcmp(option, "port") == 0 ) {
215
modopt->port = strdup(value);
220
if( strcmp(argv[i], "fileconf") == 0 ) {
221
modopt->fileconf = strdup(PAM_PGSQL_FILECONF);
222
} else if( strcmp(argv[i], "force") == 0 ) {
230
/* Setting password in the module options is unsafe */
231
if(force == 0 && modopt->passwd != NULL) {
232
SYSLOG("You cannot set the password in the module options, it's unsafe! If you know what you're doing use \"force\" in the options.");
233
free(modopt->passwd);
234
modopt->passwd = NULL;
237
if(modopt->fileconf == NULL)
238
modopt->fileconf = strdup(PAM_PGSQL_FILECONF);
240
read_config_file(modopt);
243
* If the required queries are no given by the user
244
* we create a default one based the given table and columns
246
if(modopt->query_auth == NULL) {
248
if(modopt->column_pwd != NULL && modopt->table != NULL && modopt->column_user != NULL) {
250
modopt->query_auth = (char *) malloc(32+strlen(modopt->column_pwd)+strlen(modopt->table)+strlen(modopt->column_user));
251
sprintf(modopt->query_auth, "select %s from %s where %s = %%u", modopt->column_pwd, modopt->table, modopt->column_user);
254
SYSLOG("Can't build auth query");
259
if(modopt->query_acct == NULL) {
261
if(modopt->column_expired != NULL && modopt->column_pwd != NULL && modopt->column_newpwd != NULL && modopt->table != NULL && modopt->column_user != NULL) {
263
modopt->query_acct = (char *) malloc(96+2*strlen(modopt->column_pwd)+strlen(modopt->table)+strlen(modopt->column_user)+2*strlen(modopt->column_expired)+2*strlen(modopt->column_newpwd));
264
sprintf(modopt->query_acct, "select (%s = 'y' OR %s = '1'), (%s = 'y' OR %s = '1'), (%s IS NULL OR %s = '') from %s where %s = %%u", modopt->column_expired, modopt->column_expired, modopt->column_newpwd, modopt->column_newpwd, modopt->column_pwd, modopt->column_pwd, modopt->table, modopt->column_user);
266
/* Expired column is null */
267
} else if(modopt->column_pwd != NULL && modopt->column_newpwd != NULL && modopt->table != NULL && modopt->column_user != NULL) {
269
modopt->query_acct = (char *) malloc(96+2*strlen(modopt->column_pwd)+strlen(modopt->table)+strlen(modopt->column_user)+2*strlen(modopt->column_newpwd));
270
sprintf(modopt->query_acct, "select false, (%s = 'y' OR %s = '1'), (%s IS NULL OR %s = '') from %s where %s = %%u", modopt->column_newpwd, modopt->column_newpwd, modopt->column_pwd, modopt->column_pwd, modopt->table, modopt->column_user);
272
/* Newpwd column is null */
273
} else if(modopt->column_expired != NULL && modopt->column_pwd != NULL && modopt->table != NULL && modopt->column_user != NULL) {
275
modopt->query_acct = (char *) malloc(96+2*strlen(modopt->column_pwd)+strlen(modopt->table)+strlen(modopt->column_user)+2*strlen(modopt->column_expired));
276
sprintf(modopt->query_acct, "select (%s = 'y' OR %s = '1'), false, (%s IS NULL OR %s = '') from %s where %s = %%u", modopt->column_newpwd, modopt->column_newpwd, modopt->column_pwd, modopt->column_pwd, modopt->table, modopt->column_user);
282
if(modopt->query_pwd == NULL) {
284
if(modopt->column_pwd != NULL && modopt->table != NULL && modopt->column_user != NULL) {
286
modopt->query_pwd = (char *) malloc(40+strlen(modopt->column_pwd)+strlen(modopt->table)+strlen(modopt->column_user));
287
sprintf(modopt->query_pwd, "update %s set %s = %%p where %s = %%u", modopt->table, modopt->column_pwd, modopt->column_user);
304
298
static void free_mod_options(modopt_t *options) {