/ [pam-modules] / trunk / pam_sql / pam_pgsql.c
To checkout: svn checkout http://svn.gnu.org.ua/sources/pam-modules/trunk/pam_sql/pam_pgsql.c
Puszcza

Contents of /trunk/pam_sql/pam_pgsql.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 63 - (show annotations)
Thu Mar 13 13:53:32 2008 UTC (13 years, 7 months ago) by gray
File MIME type: text/plain
File size: 4383 byte(s)
* configure.ac (PAM_COMMON_INCLUDES): Add -I${top_srcdir}/lib.
(AC_OUTPUT): Add lib/Makefile.
* doc/pam-modules.texi: Document `transform' option.
* Make.rules: New file.

* lib/mem.c, lib/slist.c, lib/log.c, lib/converse.c,
lib/graypam.h, lib/Makefile.am, lib/transform.c.

* pam_regex/pam_regex.c: Implement user name transformations.

* pam_fshadow/Makefile.am, pam_sql/Makefile.am:
Add ../lib/libgraypam.la to LDADD
* pam_fshadow/pam_fshadow.c, pam_sql/pam_mysql.c,
pam_sql/pam_pgsql.c, pam_sql/pam_sql.c: Use functions from ../lib.

1 /* This file is part of pam-modules.
2 Copyright (C) 2005, 2006, 2007, 2008 Sergey Poznyakoff
3
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 3 of the License, or (at your
7 option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program. If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <graypam.h>
18 #include <libpq-fe.h>
19
20 #include "pam_sql.c"
21
22 static char *
23 sql_escape_string (const char *ustr)
24 {
25 char *str, *q;
26 const unsigned char *p;
27 size_t len = strlen (ustr);
28 #define ESCAPABLE_CHAR "\\'\""
29
30 for (p = (const unsigned char *) ustr; *p; p++) {
31 if (strchr (ESCAPABLE_CHAR, *p))
32 len++;
33 }
34
35 str = malloc (len + 1);
36 if (!str)
37 return NULL;
38
39 for (p = (const unsigned char *) ustr, q = str; *p; p++) {
40 if (strchr (ESCAPABLE_CHAR, *p))
41 *q++ = '\\';
42 *q++ = *p;
43 }
44 *q = 0;
45 return str;
46 }
47
48 static char *
49 sql_expand_query (const char *query, const char *user, const char *pass)
50 {
51 char *p, *q, *res;
52 int len;
53 char *esc_user = NULL;
54 char *esc_pass = NULL;
55
56 if (!query)
57 return NULL;
58
59 /* Compute resulting query length */
60 for (len = 0, p = (char *) query; *p; ) {
61 if (*p == '%') {
62 if (p[1] == 'u') {
63 esc_user = sql_escape_string(user);
64 len += strlen (esc_user);
65 p += 2;
66 } if (p[1] == 'p') {
67 esc_pass = sql_escape_string(pass);
68 len += strlen (esc_pass);
69 p += 2;
70 } else if (p[1] == '%') {
71 len++;
72 p += 2;
73 } else {
74 len++;
75 p++;
76 }
77 } else {
78 len++;
79 p++;
80 }
81 }
82
83 res = malloc (len + 1);
84 if (!res) {
85 free (esc_user);
86 free (esc_pass);
87 return res;
88 }
89
90 for (p = (char *) query, q = res; *p; ) {
91 if (*p == '%') {
92 switch (*++p) {
93 case 'u':
94 strcpy (q, esc_user);
95 q += strlen (q);
96 p++;
97 break;
98
99 case 'p':
100 strcpy (q, esc_pass);
101 q += strlen (q);
102 p++;
103 break;
104
105 case '%':
106 *q++ = *p++;
107 break;
108
109 default:
110 *q++ = *p++;
111 }
112 } else
113 *q++ = *p++;
114 }
115 *q = 0;
116
117 free (esc_user);
118 free (esc_pass);
119 return res;
120 }
121
122 static int
123 verify_user_pass(const char *username, const char *password)
124 {
125 PGconn *pgconn;
126 PGresult *res;
127 char *hostname;
128 char *login;
129 char *pass;
130 char *db;
131 char *port;
132 char *query, *exquery;
133 int rc;
134
135 hostname = find_config("host");
136 CHKVAR(hostname);
137
138 port = find_config("port");
139 CHKVAR(port);
140
141 login = find_config("login");
142 CHKVAR(login);
143
144 pass = find_config("pass");
145 CHKVAR(pass);
146
147 db = find_config("db");
148 CHKVAR(db);
149
150 query = find_config("query");
151 CHKVAR(query);
152
153 exquery = sql_expand_query (query, username, password);
154 if (!exquery) {
155 _pam_log(LOG_ERR, "cannot expand query");
156 return PAM_SERVICE_ERR;
157 }
158
159 pgconn = PQsetdbLogin (hostname, port, NULL, NULL,
160 db, login, password);
161 if (PQstatus (pgconn) == CONNECTION_BAD) {
162 _pam_log(LOG_ERR, "cannot connect to database");
163 return PAM_SERVICE_ERR;
164 }
165
166 DEBUG(10,("Executing %s", exquery));
167 res = PQexec (pgconn, exquery);
168 if (res == NULL) {
169 _pam_log(LOG_ERR, "PQexec: %s", PQerrorMessage(pgconn));
170 rc = PAM_SERVICE_ERR;
171 } else if (PQresultStatus(res) != PGRES_TUPLES_OK) {
172 _pam_log(LOG_ERR, "PQexec: query did not return tuples");
173 rc = PAM_SERVICE_ERR;
174 } else {
175 char *p;
176 int n;
177
178 n = PQntuples(res);
179 DEBUG(20,("Returned %d tuples", n));
180 if (n != 1) {
181 _pam_log(LOG_WARNING,
182 "PQexec: query returned %d tuples", n);
183 if (n == 0) {
184 PQclear(res);
185 PQfinish(pgconn);
186 return PAM_SERVICE_ERR;
187 }
188 }
189
190 n = PQnfields(res);
191 DEBUG(20,("Returned %d fields", n));
192 if (n != 1) {
193 _pam_log(LOG_WARNING,
194 "PQexec: query returned %d fields", n);
195 }
196
197 p = PQgetvalue(res, 0, 0);
198 chop(p);
199 DEBUG(100,("Obtained password value: %s", p));
200
201 if (strcmp(p, crypt(password, p)) == 0)
202 rc = PAM_SUCCESS;
203 else if (rc != PAM_SUCCESS
204 && check_boolean_config ("allow-plaintext-pass", 0)) {
205 if (strcmp (p, pass) == 0)
206 rc = PAM_SUCCESS;
207 } else
208 rc = PAM_AUTH_ERR;
209 }
210
211 PQclear(res);
212 PQfinish(pgconn);
213
214 return rc;
215 }

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

Send suggestions and bug reports to Sergey Poznyakoff
ViewVC Help
Powered by ViewVC 1.1.20