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
5 module MODULE_VAR_EXPORT auth_any_module;
7 -/* Escape special characters in the input string so that the bash
8 - shell will not interpolate them when the input string is withing
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
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 */
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] == '\'')
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));
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++] = '\'';
45 - buf[buf_pos++] = s[s_pos];
48 - /* don't forget the null terminator */
49 - buf[buf_pos] = '\0';
57 - The popen() call to the external validator program is made here.
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.
64 static char *get_pw(request_rec *r, char *user, const char* password, char *auth_pwfile) {
68 - const char *rpw, *w;
71 - char *escaped_password;
73 + int fd[2], i, length = 0;
76 static char m_envstr[256]; /* sun's putenv() call is a bunch of bull malarkey */
79 - l = (char*) malloc (MAX_STRING_LEN * sizeof(char));
80 - execstr = (char*) malloc (MAX_STRING_LEN * sizeof(char));
83 - snprintf (m_envstr, 256, "%s=%s\0", "REMOTE_ADDR", r -> connection -> remote_ip);
86 - setenv ("REMOTE_ADDR", r -> connection -> remote_ip, 1);
89 - /* escape the password */
90 - escaped_password = bash_single_quote_escape_string(password);
92 - /* open the program stream */
93 - snprintf (execstr, MAX_STRING_LEN, "%s %s \'%s\'", auth_pwfile, user, escaped_password);
95 - /* free the escaped password before we forget */
96 - free(escaped_password);
97 + memset (result, '\0', sizeof(result));
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",
107 - ap_log_rerror (APLOG_MARK, APLOG_ERR, r, "Could not popen() on program: %s: %s",
108 - auth_pwfile, strerror(errno));
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",
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);
122 - if (strncmp(l, "Authentication Error", 19) == 0) /* no authorized */
124 - /* otherwise, we got a winner :), return user's real name */
127 - /* ignore the rest */
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 */
136 + /* fork failed -- clean up and return */
139 + ap_log_rerror (APLOG_MARK, APLOG_ERR, r, "Error fork()ing: %s",
145 + snprintf (m_envstr, sizeof(m_envstr), "%s=%s", "REMOTE_ADDR",
146 + r -> connection -> remote_ip);
149 + setenv ("REMOTE_ADDR", r -> connection -> remote_ip, 1);
151 + /* close open fds */
152 + i = sysconf (_SC_OPEN_MAX);
155 + fcntl (i, F_SETFD, FD_CLOEXEC);
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);
166 + execl (auth_pwfile, auth_pwfile, user, password, NULL);
170 + /* parent: read what the child has to say, if anything */
173 + i = read (fd[0], result + length, sizeof(result) - length - 1);
177 + } while ((i != -1) && (i != 0) && (length < (sizeof(result) - 1)));
182 - while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {
183 - if ((l[0] == '#') || (!l[0]))
186 - w = ap_getword(r->pool, &rpw, ':');
188 - if (!strcmp(user, w)) {
189 - ap_cfg_closefile(f);
190 - return ap_getword(r->pool, &rpw, ':');
192 + while ((length > 0) &&
193 + ((result[length - 1] == '\r') || (result[length - 1] == '\n'))) {
194 + result[--length] = '\0';
196 - ap_cfg_closefile(f);
200 + if ((strlen(result) == 0) ||
201 + (strncmp(result, "Authentication Error", 19) == 0)) /* not authorized */
204 + /* otherwise, we got a winner :), return user's real name */
205 + return strdup(result);
208 static table *groups_for_user(pool *p, char *user, char *grpfile)
210 conn_rec *c = r->connection;
217 if ((res = ap_get_basic_auth_pw(r, &sent_pw)))
221 const array_header *reqs_arr = ap_requires(r);
226 /* BUG FIX: tadc, 11-Nov-1995. If there is no "requires" directive,
227 * then any user will do.