/* * Reads the tokens from the file into an array which is returned via * the 'ary' parameter. The caller is responsable for freeing the * array. * * Returns 0 on success and 1 on failure. */ static int read_token_array(FILE * f, char **ary, unsigned int *n){ struct list_node *head, *p; unsigned int i; char *a; head = read_token_list(f, n); if (!head) return 1; a = malloc(sizeof(*a) * *n); if (!a) { perror("malloc failed"); free_token_list(head); return 1; } i = *n - 1; p = head; while (p) { a[i] = p->val; p = p->next; i -= 1; } *ary = a; free_token_list(head); return 0; }
/* Removes hop-by-hop headers listed in section 13.5.1 of RFC 2616, and additionally removes any headers listed in the Connection header as described in section 14.10. */ int http_header_remove_hop_by_hop(struct http_header **header) { static const char *HOP_BY_HOP_HEADERS[] = { "Connection", "Keep-Alive", "Proxy-Authenticate", "Proxy-Authorization", "TE", "Trailers", "Transfer-Encoding", "Upgrade", }; char *connection; char **connection_tokens; size_t num_connection_tokens; unsigned int i; connection = http_header_get(*header, "Connection"); if (connection != NULL) { const char *p; p = read_token_list(connection, &connection_tokens, &num_connection_tokens); if (p == NULL) { free(connection); return 400; } if (*p != '\0') { free(connection); for (i = 0; i < num_connection_tokens; i++) free(connection_tokens[i]); free(connection_tokens); return 400; } free(connection); } else { connection_tokens = NULL; num_connection_tokens = 0; } for (i = 0; i < sizeof(HOP_BY_HOP_HEADERS) / sizeof(HOP_BY_HOP_HEADERS[0]); i++) *header = http_header_remove(*header, HOP_BY_HOP_HEADERS[i]); for (i = 0; i < num_connection_tokens; i++) *header = http_header_remove(*header, connection_tokens[i]); for (i = 0; i < num_connection_tokens; i++) free(connection_tokens[i]); free(connection_tokens); return 0; }
static const char *http_read_challenge(const char *s, struct http_challenge *challenge) { const char *p; char *scheme; http_challenge_init(challenge); scheme = NULL; s = read_token(s, &scheme); if (s == NULL) goto bail; if (str_equal_i(scheme, "Basic")) { challenge->scheme = AUTH_BASIC; } else if (str_equal_i(scheme, "Digest")) { challenge->scheme = AUTH_DIGEST; } else { challenge->scheme = AUTH_UNKNOWN; } free(scheme); scheme = NULL; /* RFC 2617, section 1.2, requires at least one auth-param: challenge = auth-scheme 1*SP 1#auth-param But there are some schemes (NTLM and Negotiate) that can be without auth-params, so we allow that here. A comma indicates the end of this challenge and the beginning of the next (see the comment in the loop below). */ while (is_space_char(*s)) s++; if (*s == ',') { s++; while (is_space_char(*s)) s++; if (*s == '\0') goto bail; return s; } while (*s != '\0') { char *name, *value; p = read_token(s, &name); if (p == NULL) goto bail; while (is_space_char(*p)) p++; /* It's possible that we've hit the end of one challenge and the beginning of another. Section 14.33 says that the header value can be 1#challenge, in other words several challenges separated by commas. Because the auth-params are also separated by commas, the only way we can tell is if we find a token not followed by an equals sign. */ if (*p != '=') break; p++; while (is_space_char(*p)) p++; p = read_token_or_quoted_string(p, &value); if (p == NULL) { free(name); goto bail; } if (str_equal_i(name, "realm")) challenge->realm = Strdup(value); else if (challenge->scheme == AUTH_DIGEST) { if (str_equal_i(name, "nonce")) { if (challenge->digest.nonce != NULL) goto bail; challenge->digest.nonce = Strdup(value); } else if (str_equal_i(name, "opaque")) { if (challenge->digest.opaque != NULL) goto bail; challenge->digest.opaque = Strdup(value); } else if (str_equal_i(name, "algorithm")) { if (str_equal_i(value, "MD5")) challenge->digest.algorithm = ALGORITHM_MD5; else challenge->digest.algorithm = ALGORITHM_UNKNOWN; } else if (str_equal_i(name, "qop")) { char **tokens; size_t n; int i; const char *tmp; tmp = read_token_list(value, &tokens, &n); if (tmp == NULL) { free(name); free(value); goto bail; } for (i = 0; i < n; i++) { if (str_equal_i(tokens[i], "auth")) challenge->digest.qop |= QOP_AUTH; else if (str_equal_i(tokens[i], "auth-int")) challenge->digest.qop |= QOP_AUTH_INT; } for (i = 0; i < n; i++) free(tokens[i]); free(tokens); if (*tmp != '\0') { free(name); free(value); goto bail; } } } free(name); free(value); while (is_space_char(*p)) p++; if (*p == ',') { p++; while (is_space_char(*p)) p++; if (*p == '\0') goto bail; } s = p; } return s; bail: if (scheme != NULL) free(scheme); http_challenge_free(challenge); return NULL; }