]>
Commit | Line | Data |
---|---|---|
c414d14c | 1 | --- mod_auth_any-1.2.2/src/mod_auth_any.c.fork 2002-07-02 15:40:25.000000000 -0400 |
2 | +++ mod_auth_any-1.2.2/src/mod_auth_any.c 2003-03-19 12:47:44.000000000 -0500 | |
3 | @@ -170,127 +170,98 @@ | |
4 | ||
5 | module MODULE_VAR_EXPORT auth_any_module; | |
6 | ||
7 | -/* Escape special characters in the input string so that the bash | |
8 | - shell will not interpolate them when the input string is withing | |
9 | - single quotes. | |
10 | - | |
11 | - IN: null-terminated character array containing string to be interpolated | |
12 | - OUT: newly allocate (using malloc) null-terminated character array | |
13 | - containing the input string with the special characters properly | |
14 | - escaped */ | |
15 | -char* bash_single_quote_escape_string(const char *s) { | |
16 | - /* used to count the length of the string and the number of single quotes */ | |
17 | - int str_len, sq_count; | |
18 | - int s_pos, buf_pos; /* copy chars loop counter */ | |
19 | - /* used to hold the final result string */ | |
20 | - char *buf; | |
21 | - | |
22 | - /* Count the single quotes. | |
23 | - LOOP INVARIANT: str_len < (number of chars in string 's') | |
24 | - POSTCONDITION: sq_count == (number of single quotes in string 's') */ | |
25 | - for (str_len = 0, sq_count = 0; s[str_len] != '\0'; str_len++) | |
26 | - if (s[str_len] == '\'') | |
27 | - sq_count++; | |
28 | - | |
29 | - /* Allocate the memory for the final string. | |
30 | - Each ' (one char) will become '\'' (4 chars), so multiply by 4 | |
31 | - and don't forget to add 1 for terminating null. */ | |
32 | - buf = (char*) malloc(sizeof(char) * (str_len + 1 + sq_count * 4)); | |
33 | - | |
34 | - /* Copy the chars of 's' into 'buf', turning each ' into '\'' */ | |
35 | - for (s_pos = 0, buf_pos = 0; s_pos < str_len; s_pos++) { | |
36 | - /* If we see a single quote, then put '\'' into 'buf' and advance | |
37 | - buf_pos 4 positions, else put the next char from 's' into 'buf' | |
38 | - and advance buf_pos 1 position. */ | |
39 | - if(s[s_pos] == '\'') { | |
40 | - buf[buf_pos++] = '\''; | |
41 | - buf[buf_pos++] = '\\'; | |
42 | - buf[buf_pos++] = '\''; | |
43 | - buf[buf_pos++] = '\''; | |
44 | - } else { | |
45 | - buf[buf_pos++] = s[s_pos]; | |
46 | - } | |
47 | - } | |
48 | - /* don't forget the null terminator */ | |
49 | - buf[buf_pos] = '\0'; | |
50 | - | |
51 | - return buf; | |
52 | -} | |
53 | - | |
54 | /* | |
55 | - nb: | |
56 | - | |
57 | - The popen() call to the external validator program is made here. | |
58 | -*/ | |
59 | + * Call the external program auth_pwfile with user and password as its | |
60 | + * arguments. These should have been passed in over a pipe, but it's too | |
61 | + * late to change that now. The called program should print the name of the | |
62 | + * valid user to stdout, or print "Authentication Error" on failure. | |
63 | + */ | |
64 | static char *get_pw(request_rec *r, char *user, const char* password, char *auth_pwfile) { | |
65 | - configfile_t *f; | |
66 | - char* execstr; | |
67 | - char* l; | |
68 | - const char *rpw, *w; | |
69 | - FILE* ext_authprog; | |
70 | - FILE* fp; | |
71 | - char *escaped_password; | |
72 | + char result[256]; | |
73 | + int fd[2], i, length = 0; | |
74 | + pid_t pid; | |
75 | #ifdef __sun | |
76 | static char m_envstr[256]; /* sun's putenv() call is a bunch of bull malarkey */ | |
77 | #endif | |
78 | - | |
79 | - l = (char*) malloc (MAX_STRING_LEN * sizeof(char)); | |
80 | - execstr = (char*) malloc (MAX_STRING_LEN * sizeof(char)); | |
81 | ||
82 | -#ifdef __sun | |
83 | - snprintf (m_envstr, 256, "%s=%s\0", "REMOTE_ADDR", r -> connection -> remote_ip); | |
84 | - putenv (m_envstr); | |
85 | -#else | |
86 | - setenv ("REMOTE_ADDR", r -> connection -> remote_ip, 1); | |
87 | -#endif | |
88 | - | |
89 | - /* escape the password */ | |
90 | - escaped_password = bash_single_quote_escape_string(password); | |
91 | - | |
92 | - /* open the program stream */ | |
93 | - snprintf (execstr, MAX_STRING_LEN, "%s %s \'%s\'", auth_pwfile, user, escaped_password); | |
94 | - | |
95 | - /* free the escaped password before we forget */ | |
96 | - free(escaped_password); | |
97 | + memset (result, '\0', sizeof(result)); | |
98 | ||
99 | - if (!(ext_authprog = popen (execstr, "r"))) { | |
100 | + /* sanity check the auth_pwfile */ | |
101 | + if ((auth_pwfile == NULL) || (auth_pwfile[0] != '/')) { | |
102 | + ap_log_rerror (APLOG_MARK, APLOG_ERR, r, "Invalid program: %s", | |
103 | + auth_pwfile); | |
104 | + return NULL; | |
105 | + } | |
106 | ||
107 | - ap_log_rerror (APLOG_MARK, APLOG_ERR, r, "Could not popen() on program: %s: %s", | |
108 | - auth_pwfile, strerror(errno)); | |
109 | - return NULL; | |
110 | + /* set up our communication pipe */ | |
111 | + if (pipe (fd) == -1) { | |
112 | + /* couldn't create pipe for some reason */ | |
113 | + ap_log_rerror (APLOG_MARK, APLOG_ERR, r, "Error creating pipe: %s", | |
114 | + strerror(errno)); | |
115 | + return NULL; | |
116 | } | |
117 | - /* whew, the popen() has seemingly succeeded, let's write the username passwd stuff*/ | |
118 | - if (feof(ext_authprog) == 0) | |
119 | - fgets (l, MAX_STRING_LEN, ext_authprog); | |
120 | - pclose (ext_authprog); | |
121 | - | |
122 | - if (strncmp(l, "Authentication Error", 19) == 0) /* no authorized */ | |
123 | - return NULL; | |
124 | - /* otherwise, we got a winner :), return user's real name */ | |
125 | - return l; | |
126 | ||
127 | - /* ignore the rest */ | |
128 | - /* | |
129 | - if (!(f = ap_pcfg_openfile(r->pool, auth_pwfile))) { | |
130 | - ap_log_rerror(APLOG_MARK, APLOG_ERR, r, | |
131 | - "Could not open password file: %s", auth_pwfile); | |
132 | + /* start our child */ | |
133 | + pid = fork (); | |
134 | + switch (pid) { | |
135 | + case -1: | |
136 | + /* fork failed -- clean up and return */ | |
137 | + close (fd[0]); | |
138 | + close (fd[1]); | |
139 | + ap_log_rerror (APLOG_MARK, APLOG_ERR, r, "Error fork()ing: %s", | |
140 | + strerror (errno)); | |
141 | return NULL; | |
142 | + break; | |
143 | + case 0: | |
144 | +#ifdef __sun | |
145 | + snprintf (m_envstr, sizeof(m_envstr), "%s=%s", "REMOTE_ADDR", | |
146 | + r -> connection -> remote_ip); | |
147 | + putenv (m_envstr); | |
148 | +#else | |
149 | + setenv ("REMOTE_ADDR", r -> connection -> remote_ip, 1); | |
150 | +#endif | |
151 | + /* close open fds */ | |
152 | + i = sysconf (_SC_OPEN_MAX); | |
153 | + while (i >= 0) { | |
154 | + if (i != fd[1]) { | |
155 | + fcntl (i, F_SETFD, FD_CLOEXEC); | |
156 | + } | |
157 | + i--; | |
158 | + } | |
159 | + /* make the write end of the pipe our stdout */ | |
160 | + if (fd[1] != STDOUT_FILENO) { | |
161 | + close (STDOUT_FILENO); | |
162 | + dup2 (fd[1], STDOUT_FILENO); | |
163 | + fcntl (STDOUT_FILENO, F_SETFD, 0); | |
164 | + fcntl (fd[1], F_SETFD, FD_CLOEXEC); | |
165 | + } | |
166 | + execl (auth_pwfile, auth_pwfile, user, password, NULL); | |
167 | + _exit (1); | |
168 | + break; | |
169 | + default: | |
170 | + /* parent: read what the child has to say, if anything */ | |
171 | + close (fd[1]); | |
172 | + do { | |
173 | + i = read (fd[0], result + length, sizeof(result) - length - 1); | |
174 | + if (i != -1) { | |
175 | + length += i; | |
176 | + } | |
177 | + } while ((i != -1) && (i != 0) && (length < (sizeof(result) - 1))); | |
178 | + close (fd[0]); | |
179 | + break; | |
180 | } | |
181 | - | |
182 | - while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) { | |
183 | - if ((l[0] == '#') || (!l[0])) | |
184 | - continue; | |
185 | - rpw = l; | |
186 | - w = ap_getword(r->pool, &rpw, ':'); | |
187 | ||
188 | - if (!strcmp(user, w)) { | |
189 | - ap_cfg_closefile(f); | |
190 | - return ap_getword(r->pool, &rpw, ':'); | |
191 | - } | |
192 | + while ((length > 0) && | |
193 | + ((result[length - 1] == '\r') || (result[length - 1] == '\n'))) { | |
194 | + result[--length] = '\0'; | |
195 | } | |
196 | - ap_cfg_closefile(f); | |
197 | - return NULL; | |
198 | - */ | |
199 | + | |
200 | + if ((strlen(result) == 0) || | |
201 | + (strncmp(result, "Authentication Error", 19) == 0)) /* not authorized */ | |
202 | + return NULL; | |
203 | + | |
204 | + /* otherwise, we got a winner :), return user's real name */ | |
205 | + return strdup(result); | |
206 | } | |
207 | ||
208 | static table *groups_for_user(pool *p, char *user, char *grpfile) | |
209 | @@ -351,9 +322,7 @@ | |
210 | conn_rec *c = r->connection; | |
211 | const char *sent_pw; | |
212 | char *real_pw; | |
213 | - char *invalid_pw; | |
214 | int res; | |
215 | - FILE* fp; | |
216 | ||
217 | if ((res = ap_get_basic_auth_pw(r, &sent_pw))) | |
218 | return res; | |
219 | @@ -423,8 +392,6 @@ | |
220 | table *grpstatus; | |
221 | const array_header *reqs_arr = ap_requires(r); | |
222 | require_line *reqs; | |
223 | - FILE* fp; | |
224 | - | |
225 | ||
226 | /* BUG FIX: tadc, 11-Nov-1995. If there is no "requires" directive, | |
227 | * then any user will do. |