X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fcups.git;a=blobdiff_plain;f=cgi-bin%2Fvar.c;h=90ab8bb526125d379a6c677d4140c52d0dc1305c;hp=1467bd878d4f5fd0b0089f53d1c4cac15d128301;hb=7e86f2f686334cb3db458b4585dfce9c1b712bc4;hpb=ef55b7453303a9a2b20590815c967d044a13da1d diff --git a/cgi-bin/var.c b/cgi-bin/var.c index 1467bd878..90ab8bb52 100644 --- a/cgi-bin/var.c +++ b/cgi-bin/var.c @@ -1,45 +1,33 @@ /* - * "$Id: var.c 7460 2008-04-16 02:19:54Z mike $" + * "$Id$" * - * CGI form variable and array functions. + * CGI form variable and array functions for CUPS. * - * Copyright 2007-2009 by Apple Inc. - * Copyright 1997-2005 by Easy Software Products. + * Copyright 2007-2014 by Apple Inc. + * Copyright 1997-2005 by Easy Software Products. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cgiCheckVariables() - Check for the presence of "required" variables. - * cgiClearVariables() - Clear all form variables. - * cgiGetArray() - Get an element from a form array... - * cgiGetFile() - Get the file (if any) that was submitted in the form. - * cgiGetSize() - Get the size of a form array value. - * cgiGetVariable() - Get a CGI variable from the database... - * cgiInitialize() - Initialize the CGI variable "database"... - * cgiIsPOST() - Determine whether this page was POSTed. - * cgiSetArray() - Set array element N to the specified string. - * cgiSetSize() - Set the array size. - * cgiSetVariable() - Set a CGI variable in the database... - * cgi_add_variable() - Add a form variable. - * cgi_compare_variables() - Compare two variables. - * cgi_find_variable() - Find a variable... - * cgi_initialize_get() - Initialize form variables using the GET method. - * cgi_initialize_multipart() - Initialize variables and file using the POST method. - * cgi_initialize_post() - Initialize variables using the POST method. - * cgi_initialize_string() - Initialize form variables from a string. - * cgi_passwd() - Catch authentication requests and notify the server. - * cgi_sort_variables() - Sort all form variables for faster lookup. - * cgi_unlink_file() - Remove the uploaded form. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". + */ + +/* + * Include necessary headers... */ /*#define DEBUG*/ #include "cgi-private.h" -#include +#include +#include + + +/* + * Session ID name + */ + +#define CUPS_SID "org.cups.sid" /* @@ -59,6 +47,8 @@ typedef struct /**** Form variable structure ****/ * Local globals... */ +static int num_cookies = 0;/* Number of cookies */ +static cups_option_t *cookies = NULL;/* Cookies */ static int form_count = 0, /* Form variable count */ form_alloc = 0; /* Number of variables allocated */ static _cgi_var_t *form_vars = NULL; @@ -76,11 +66,13 @@ static void cgi_add_variable(const char *name, int element, static int cgi_compare_variables(const _cgi_var_t *v1, const _cgi_var_t *v2); static _cgi_var_t *cgi_find_variable(const char *name); +static void cgi_initialize_cookies(void); static int cgi_initialize_get(void); static int cgi_initialize_multipart(const char *boundary); static int cgi_initialize_post(void); static int cgi_initialize_string(const char *data); static const char *cgi_passwd(const char *prompt); +static const char *cgi_set_sid(void); static void cgi_sort_variables(void); static void cgi_unlink_file(void); @@ -146,6 +138,8 @@ cgiClearVariables(void) _cgi_var_t *v; /* Current variable */ + fputs("DEBUG: cgiClearVariables called.\n", stderr); + for (v = form_vars, i = form_count; i > 0; v ++, i --) { _cupsStrFree(v->name); @@ -161,7 +155,7 @@ cgiClearVariables(void) /* - * 'cgiGetArray()' - Get an element from a form array... + * 'cgiGetArray()' - Get an element from a form array. */ const char * /* O - Element value or NULL */ @@ -181,6 +175,17 @@ cgiGetArray(const char *name, /* I - Name of array variable */ } +/* + * 'cgiGetCookie()' - Get a cookie value. + */ + +const char * /* O - Value or NULL */ +cgiGetCookie(const char *name) /* I - Name of cookie */ +{ + return (cupsGetOption(name, num_cookies, cookies)); +} + + /* * 'cgiGetFile()' - Get the file (if any) that was submitted in the form. */ @@ -210,10 +215,10 @@ cgiGetSize(const char *name) /* I - Name of variable */ /* - * 'cgiGetVariable()' - Get a CGI variable from the database... + * 'cgiGetVariable()' - Get a CGI variable from the database. * * Returns NULL if the variable doesn't exist. If the variable is an - * array of values, returns the last element... + * array of values, returns the last element. */ const char * /* O - Value of variable */ @@ -237,14 +242,16 @@ cgiGetVariable(const char *name) /* I - Name of variable */ /* - * 'cgiInitialize()' - Initialize the CGI variable "database"... + * 'cgiInitialize()' - Initialize the CGI variable "database". */ int /* O - Non-zero if there was form data */ cgiInitialize(void) { - const char *method; /* Form posting method */ - const char *content_type; /* Content-Type of post data */ + const char *method, /* Form posting method */ + *content_type, /* Content-Type of post data */ + *cups_sid_cookie, /* SID cookie */ + *cups_sid_form; /* SID form variable */ /* @@ -267,6 +274,20 @@ cgiInitialize(void) setbuf(stdout, NULL); #endif /* DEBUG */ + /* + * Get cookies... + */ + + cgi_initialize_cookies(); + + if ((cups_sid_cookie = cgiGetCookie(CUPS_SID)) == NULL) + { + fputs("DEBUG: " CUPS_SID " cookie not found, initializing!\n", stderr); + cups_sid_cookie = cgi_set_sid(); + } + + fprintf(stderr, "DEBUG: " CUPS_SID " cookie is \"%s\"\n", cups_sid_cookie); + /* * Get the request method (GET or POST)... */ @@ -280,9 +301,9 @@ cgiInitialize(void) * Grab form data from the corresponding location... */ - if (!strcasecmp(method, "GET")) + if (!_cups_strcasecmp(method, "GET")) return (cgi_initialize_get()); - else if (!strcasecmp(method, "POST") && content_type) + else if (!_cups_strcasecmp(method, "POST") && content_type) { const char *boundary = strstr(content_type, "boundary="); @@ -290,9 +311,27 @@ cgiInitialize(void) boundary += 9; if (content_type && !strncmp(content_type, "multipart/form-data; ", 21)) - return (cgi_initialize_multipart(boundary)); + { + if (!cgi_initialize_multipart(boundary)) + return (0); + } + else if (!cgi_initialize_post()) + return (0); + + if ((cups_sid_form = cgiGetVariable(CUPS_SID)) == NULL || + strcmp(cups_sid_cookie, cups_sid_form)) + { + if (cups_sid_form) + fprintf(stderr, "DEBUG: " CUPS_SID " form variable is \"%s\"\n", + cups_sid_form); + else + fputs("DEBUG: " CUPS_SID " form variable is not present.\n", stderr); + + cgiClearVariables(); + return (0); + } else - return (cgi_initialize_post()); + return (1); } else return (0); @@ -335,6 +374,8 @@ cgiSetArray(const char *name, /* I - Name of variable */ if (name == NULL || value == NULL || element < 0 || element > 100000) return; + fprintf(stderr, "DEBUG: cgiSetArray: %s[%d]=\"%s\"\n", name, element, value); + if ((var = cgi_find_variable(name)) == NULL) { cgi_add_variable(name, element, value); @@ -347,7 +388,7 @@ cgiSetArray(const char *name, /* I - Name of variable */ const char **temp; /* Temporary pointer */ temp = (const char **)realloc((void *)(var->values), - sizeof(char *) * (element + 16)); + sizeof(char *) * (size_t)(element + 16)); if (!temp) return; @@ -370,6 +411,38 @@ cgiSetArray(const char *name, /* I - Name of variable */ } +/* + * 'cgiSetCookie()' - Set a cookie value. + */ + +void +cgiSetCookie(const char *name, /* I - Name */ + const char *value, /* I - Value */ + const char *path, /* I - Path (typically "/") */ + const char *domain, /* I - Domain name */ + time_t expires, /* I - Expiration date (0 for session) */ + int secure) /* I - Require SSL */ +{ + num_cookies = cupsAddOption(name, value, num_cookies, &cookies); + + printf("Set-Cookie: %s=%s;", name, value); + if (path) + printf(" path=%s;", path); + if (domain) + printf(" domain=%s;", domain); + if (expires) + { + char date[256]; /* Date string */ + + printf(" expires=%s;", httpGetDateString2(expires, date, sizeof(date))); + } + if (secure) + puts(" secure;"); + else + putchar('\n'); +} + + /* * 'cgiSetSize()' - Set the array size. */ @@ -393,7 +466,7 @@ cgiSetSize(const char *name, /* I - Name of variable */ const char **temp; /* Temporary pointer */ temp = (const char **)realloc((void *)(var->values), - sizeof(char *) * (size + 16)); + sizeof(char *) * (size_t)(size + 16)); if (!temp) return; @@ -418,7 +491,7 @@ cgiSetSize(const char *name, /* I - Name of variable */ /* - * 'cgiSetVariable()' - Set a CGI variable in the database... + * 'cgiSetVariable()' - Set a CGI variable in the database. * * If the variable is an array, this truncates the array to a single element. */ @@ -434,6 +507,8 @@ cgiSetVariable(const char *name, /* I - Name of variable */ if (name == NULL || value == NULL) return; + fprintf(stderr, "cgiSetVariable: %s=\"%s\"\n", name, value); + if ((var = cgi_find_variable(name)) == NULL) { cgi_add_variable(name, 0, value); @@ -477,7 +552,7 @@ cgi_add_variable(const char *name, /* I - Variable name */ if (form_alloc == 0) temp_vars = malloc(sizeof(_cgi_var_t) * 16); else - temp_vars = realloc(form_vars, (form_alloc + 16) * sizeof(_cgi_var_t)); + temp_vars = realloc(form_vars, (size_t)(form_alloc + 16) * sizeof(_cgi_var_t)); if (!temp_vars) return; @@ -488,7 +563,7 @@ cgi_add_variable(const char *name, /* I - Variable name */ var = form_vars + form_count; - if ((var->values = calloc(element + 1, sizeof(char *))) == NULL) + if ((var->values = calloc((size_t)element + 1, sizeof(char *))) == NULL) return; var->name = _cupsStrAlloc(name); @@ -509,12 +584,12 @@ cgi_compare_variables( const _cgi_var_t *v1, /* I - First variable */ const _cgi_var_t *v2) /* I - Second variable */ { - return (strcasecmp(v1->name, v2->name)); + return (_cups_strcasecmp(v1->name, v2->name)); } /* - * 'cgi_find_variable()' - Find a variable... + * 'cgi_find_variable()' - Find a variable. */ static _cgi_var_t * /* O - Variable pointer or NULL */ @@ -528,11 +603,96 @@ cgi_find_variable(const char *name) /* I - Name of variable */ key.name = name; - return ((_cgi_var_t *)bsearch(&key, form_vars, form_count, sizeof(_cgi_var_t), + return ((_cgi_var_t *)bsearch(&key, form_vars, (size_t)form_count, sizeof(_cgi_var_t), (int (*)(const void *, const void *))cgi_compare_variables)); } +/* + * 'cgi_initialize_cookies()' - Initialize cookies. + */ + +static void +cgi_initialize_cookies(void) +{ + const char *cookie; /* HTTP_COOKIE environment variable */ + char name[128], /* Name string */ + value[512], /* Value string */ + *ptr; /* Pointer into name/value */ + + + if ((cookie = getenv("HTTP_COOKIE")) == NULL) + return; + + while (*cookie) + { + /* + * Skip leading whitespace... + */ + + while (isspace(*cookie & 255)) + cookie ++; + if (!*cookie) + break; + + /* + * Copy the name... + */ + + for (ptr = name; *cookie && *cookie != '=';) + if (ptr < (name + sizeof(name) - 1)) + *ptr++ = *cookie++; + else + break; + + if (*cookie != '=') + break; + + *ptr = '\0'; + cookie ++; + + /* + * Then the value... + */ + + if (*cookie == '\"') + { + for (cookie ++, ptr = value; *cookie && *cookie != '\"';) + if (ptr < (value + sizeof(value) - 1)) + *ptr++ = *cookie++; + else + break; + + if (*cookie == '\"') + cookie ++; + } + else + { + for (ptr = value; *cookie && *cookie != ';';) + if (ptr < (value + sizeof(value) - 1)) + *ptr++ = *cookie++; + else + break; + } + + if (*cookie == ';') + cookie ++; + else if (*cookie) + break; + + *ptr = '\0'; + + /* + * Then add the cookie to an array as long as the name doesn't start with + * "$"... + */ + + if (name[0] != '$') + num_cookies = cupsAddOption(name, value, num_cookies, &cookies); + } +} + + /* * 'cgi_initialize_get()' - Initialize form variables using the GET method. */ @@ -562,7 +722,8 @@ cgi_initialize_get(void) /* - * 'cgi_initialize_multipart()' - Initialize variables and file using the POST method. + * 'cgi_initialize_multipart()' - Initialize variables and file using the POST + * method. * * TODO: Update to support files > 2GB. */ @@ -579,8 +740,8 @@ cgi_initialize_multipart( *ptr, /* Pointer into name/filename */ *end; /* End of buffer */ int ch, /* Character from file */ - fd, /* Temporary file descriptor */ - blen; /* Length of boundary string */ + fd; /* Temporary file descriptor */ + size_t blen; /* Length of boundary string */ DEBUG_printf(("cgi_initialize_multipart(boundary=\"%s\")\n", boundary)); @@ -640,20 +801,20 @@ cgi_initialize_multipart( /* * Copy file data to the temp file... */ - + ptr = line; while ((ch = getchar()) != EOF) { - *ptr++ = ch; + *ptr++ = (char)ch; - if ((ptr - line) >= blen && !memcmp(ptr - blen, bstring, blen)) + if ((size_t)(ptr - line) >= blen && !memcmp(ptr - blen, bstring, blen)) { ptr -= blen; break; } - if ((ptr - line - blen) >= 8192) + if ((ptr - line - (int)blen) >= 8192) { /* * Write out the first 8k of the buffer... @@ -670,7 +831,7 @@ cgi_initialize_multipart( */ if (ptr > line) - write(fd, line, ptr - line); + write(fd, line, (size_t)(ptr - line)); close(fd); } @@ -687,9 +848,9 @@ cgi_initialize_multipart( while ((ch = getchar()) != EOF) { if (ptr < end) - *ptr++ = ch; + *ptr++ = (char)ch; - if ((ptr - line) >= blen && !memcmp(ptr - blen, bstring, blen)) + if ((size_t)(ptr - line) >= blen && !memcmp(ptr - blen, bstring, blen)) { ptr -= blen; break; @@ -744,7 +905,7 @@ cgi_initialize_multipart( filename[0] = '\0'; mimetype[0] = '\0'; } - else if (!strncasecmp(line, "Content-Disposition:", 20)) + else if (!_cups_strncasecmp(line, "Content-Disposition:", 20)) { if ((ptr = strstr(line + 20, " name=\"")) != NULL) { @@ -762,7 +923,7 @@ cgi_initialize_multipart( *ptr = '\0'; } } - else if (!strncasecmp(line, "Content-Type:", 13)) + else if (!_cups_strncasecmp(line, "Content-Type:", 13)) { for (ptr = line + 13; isspace(*ptr & 255); ptr ++); @@ -789,12 +950,12 @@ cgi_initialize_multipart( static int /* O - 1 if form data was read */ cgi_initialize_post(void) { - char *content_length, /* Length of input data (string) */ - *data; /* Pointer to form data string */ - int length, /* Length of input data */ - nbytes, /* Number of bytes read this read() */ - tbytes, /* Total number of bytes read */ - status; /* Return status */ + char *content_length, /* Length of input data (string) */ + *data; /* Pointer to form data string */ + size_t length, /* Length of input data */ + tbytes; /* Total number of bytes read */ + ssize_t nbytes; /* Number of bytes read this read() */ + int status; /* Return status */ DEBUG_puts("cgi_initialize_post: Initializing variables using POST method..."); @@ -811,7 +972,7 @@ cgi_initialize_post(void) * Get the length of the input stream and allocate a buffer for it... */ - length = atoi(content_length); + length = (size_t)strtol(content_length, NULL, 10); data = malloc(length + 1); if (data == NULL) @@ -821,8 +982,8 @@ cgi_initialize_post(void) * Read the data into the buffer... */ - for (tbytes = 0; tbytes < length; tbytes += nbytes) - if ((nbytes = read(0, data + tbytes, length - tbytes)) < 0) + for (tbytes = 0; tbytes < length; tbytes += (size_t)nbytes) + if ((nbytes = read(0, data + tbytes, (size_t)(length - tbytes))) < 0) { if (errno != EAGAIN) { @@ -874,7 +1035,7 @@ cgi_initialize_string(const char *data) /* I - Form data string */ char *s, /* Pointer to current form string */ ch, /* Temporary character */ name[255], /* Name of form variable */ - value[65536]; /* Variable value... */ + value[65536]; /* Variable value */ /* @@ -927,13 +1088,16 @@ cgi_initialize_string(const char *data) /* I - Form data string */ * Read the hex code... */ + if (!isxdigit(data[1] & 255) || !isxdigit(data[2] & 255)) + return (0); + if (s < (value + sizeof(value) - 1)) { data ++; ch = *data - '0'; if (ch > 9) ch -= 7; - *s = ch << 4; + *s = (char)(ch << 4); data ++; ch = *data - '0'; @@ -1014,6 +1178,46 @@ cgi_passwd(const char *prompt) /* I - Prompt (not used) */ } +/* + * 'cgi_set_sid()' - Set the CUPS session ID. + */ + +static const char * /* O - New session ID */ +cgi_set_sid(void) +{ + char buffer[512], /* SID data */ + sid[33]; /* SID string */ + _cups_md5_state_t md5; /* MD5 state */ + unsigned char sum[16]; /* MD5 sum */ + const char *remote_addr, /* REMOTE_ADDR */ + *server_name, /* SERVER_NAME */ + *server_port; /* SERVER_PORT */ + + + if ((remote_addr = getenv("REMOTE_ADDR")) == NULL) + remote_addr = "REMOTE_ADDR"; + if ((server_name = getenv("SERVER_NAME")) == NULL) + server_name = "SERVER_NAME"; + if ((server_port = getenv("SERVER_PORT")) == NULL) + server_port = "SERVER_PORT"; + + CUPS_SRAND(time(NULL)); + snprintf(buffer, sizeof(buffer), "%s:%s:%s:%02X%02X%02X%02X%02X%02X%02X%02X", + remote_addr, server_name, server_port, + (unsigned)CUPS_RAND() & 255, (unsigned)CUPS_RAND() & 255, + (unsigned)CUPS_RAND() & 255, (unsigned)CUPS_RAND() & 255, + (unsigned)CUPS_RAND() & 255, (unsigned)CUPS_RAND() & 255, + (unsigned)CUPS_RAND() & 255, (unsigned)CUPS_RAND() & 255); + _cupsMD5Init(&md5); + _cupsMD5Append(&md5, (unsigned char *)buffer, (int)strlen(buffer)); + _cupsMD5Finish(&md5, sum); + + cgiSetCookie(CUPS_SID, httpMD5String(sum, sid), "/", NULL, 0, 0); + + return (cupsGetOption(CUPS_SID, num_cookies, cookies)); +} + + /* * 'cgi_sort_variables()' - Sort all form variables for faster lookup. */ @@ -1031,7 +1235,7 @@ cgi_sort_variables(void) if (form_count < 2) return; - qsort(form_vars, form_count, sizeof(_cgi_var_t), + qsort(form_vars, (size_t)form_count, sizeof(_cgi_var_t), (int (*)(const void *, const void *))cgi_compare_variables); #ifdef DEBUG @@ -1074,5 +1278,5 @@ cgi_unlink_file(void) /* - * End of "$Id: var.c 7460 2008-04-16 02:19:54Z mike $". + * End of "$Id$". */