Index: b/common/simple-pwquery.c =================================================================== --- b/common/simple-pwquery.c +++ b/common/simple-pwquery.c @@ -307,6 +307,125 @@ } +#ifndef HAVE_W32_SYSTEM +/* Find a redirected socket name for fname and return a malloced setup + filled sockaddr. If this does not work out NULL is returned and + ERRNO is set. If the file seems to be a redirect True is stored at + R_REDIRECT. Note that this function uses the standard malloc and + not the assuan wrapped one. The format of the file is: + + %Assuan% + socket=NAME + + where NAME is the actual socket to use. No white spaces are + allowed, both lines must be terminated by a single LF, extra lines + are not allowed. Environment variables are interpreted in NAME if + given in "${VAR} notation; no escape characters are defined, if + "${" shall be used verbatim, you need to use an environment + variable with that content. + + The use of an absolute NAME is strongly suggested. The length of + the file is limited to 511 bytes which is more than sufficient for + that common value of 107 for sun_path. */ +static struct sockaddr_un * +eval_redirection (const char *fname, int *r_redirect) +{ + FILE *fp; + char buffer[512], *name; + size_t n; + struct sockaddr_un *addr; + char *p, *pend; + const char *s; + + *r_redirect = 0; + + fp = fopen (fname, "rb"); + if (!fp) + return NULL; + n = fread (buffer, 1, sizeof buffer - 1, fp); + fclose (fp); + if (!n) + { +#ifdef SPWQ_USE_LOGGING + log_error ("Emprt file: %s\n", fname ); +#endif + return NULL; + } + buffer[n] = 0; + + /* Check that it is a redirection file. We also check that the + first byte of the name is not a LF because that would lead to an + zero length name. */ + if (n < 17 || buffer[n-1] != '\n' + || memcmp (buffer, "%Assuan%\nsocket=", 16) + || buffer[16] == '\n') + { +#ifdef SPWQ_USE_LOGGING + log_error ("Invalid content in: %s\n", fname ); +#endif + return NULL; + } + buffer[n-1] = 0; + name = buffer + 16; + + *r_redirect = 1; + + addr = calloc (1, sizeof *addr); + if (!addr) + return NULL; + addr->sun_family = AF_LOCAL; + + n = 0; + for (p=name; *p; p++) + { + if (*p == '$' && p[1] == '{') + { + p += 2; + pend = strchr (p, '}'); + if (!pend) + { + free (addr); +#ifdef SPWQ_USE_LOGGING + log_error ("Invalid variable syntax in: %s\n", fname ); +#endif + return NULL; + } + *pend = 0; + if (*p && (s = getenv (p))) + { + for (; *s; s++) + { + if (n < sizeof addr->sun_path - 1) + addr->sun_path[n++] = *s; + else + { + free (addr); +#ifdef SPWQ_USE_LOGGING + log_error ("Redirected soclet name too long after evaluation in %s\n", fname ); +#endif + return NULL; + } + } + } + p = pend; + } + else if (*p == '\n') + break; /* Be nice and stop at the first LF. */ + else if (n < sizeof addr->sun_path - 1) + addr->sun_path[n++] = *p; + else + { + free (addr); +#ifdef SPWQ_USE_LOGGING + log_error ("Redirected soclet name too long %s\n", fname ); +#endif + return NULL; + } + } + + return addr; +} +#endif /*!HAVE_W32_SYSTEM*/ /* Try to open a connection to the agent, send all options and return the file descriptor for the connection. Return -1 in case of @@ -318,6 +437,8 @@ int fd; char *infostr, *p; struct sockaddr_un client_addr; + struct sockaddr_un *unaddr_new; + int redirect; size_t len; char line[200]; int nread; @@ -337,8 +458,7 @@ strcpy (p, infostr); infostr = p; - if ( !(p = strchr ( infostr, PATHSEP_C)) || p == infostr - || (p-infostr)+1 >= sizeof client_addr.sun_path ) + if ( !(p = strchr ( infostr, PATHSEP_C)) || p == infostr ) { return SPWQ_NO_AGENT; } @@ -360,9 +480,23 @@ return SPWQ_SYS_ERROR; } - memset (&client_addr, 0, sizeof client_addr); - client_addr.sun_family = AF_UNIX; - strcpy (client_addr.sun_path, infostr); +#ifndef HAVE_W32_SYSTEM + unaddr_new = eval_redirection (infostr, &redirect); + if (unaddr_new) + { + memcpy (&client_addr, unaddr_new, sizeof client_addr); + free (unaddr_new); + } + else if (redirect) { + return SPWQ_NO_AGENT; + } + else +#endif + { + memset (&client_addr, 0, sizeof client_addr); + client_addr.sun_family = AF_UNIX; + strcpy (client_addr.sun_path, infostr); + } len = SUN_LEN (&client_addr); #ifdef HAVE_W32_SYSTEM