static char *http_connect_request_auth(const union sockaddr_u *su, int *n, struct http_challenge *challenge) { char *buf = NULL; size_t size = 0, offset = 0; append_connect_request_line(&buf, &size, &offset, su); strbuf_append_str(&buf, &size, &offset, "Proxy-Authorization:"); if (challenge->scheme == AUTH_BASIC) { char *auth_str; auth_str = b64enc((unsigned char *) o.proxy_auth, strlen(o.proxy_auth)); strbuf_sprintf(&buf, &size, &offset, " Basic %s\r\n", auth_str); free(auth_str); #if HAVE_HTTP_DIGEST } else if (challenge->scheme == AUTH_DIGEST) { char *proxy_auth; char *username, *password; char *response_hdr; /* Split up the proxy auth argument. */ proxy_auth = Strdup(o.proxy_auth); username = strtok(proxy_auth, ":"); password = strtok(NULL, ":"); if (password == NULL) { free(proxy_auth); return NULL; } response_hdr = http_digest_proxy_authorization(challenge, username, password, "CONNECT", sock_to_url(&httpconnect)); if (response_hdr == NULL) { free(proxy_auth); return NULL; } strbuf_append_str(&buf, &size, &offset, response_hdr); free(proxy_auth); free(response_hdr); #endif } else { bye("Unknown authentication type."); } strbuf_append_str(&buf, &size, &offset, "\r\n"); *n = offset; return buf; }
char *encrypt_string(const char *keydata, char *in) { size_t len = 0; unsigned char *bdata = NULL; char *res = NULL; len = strlen(in); bdata = aes_encrypt_ecb_binary(keydata, (unsigned char *) in, &len); if (likely(keydata && *keydata)) { res = b64enc(bdata, len); OPENSSL_cleanse(bdata, len); free(bdata); return res; } else { return (char *) bdata; } }
/* userpass is a user:pass string (the argument to --proxy-auth). value is the value of the Proxy-Authorization header field. Returns 0 on authentication failure and nonzero on success. *stale is set to 1 if HTTP Digest credentials are valid but out of date. */ static int check_auth(const struct http_request *request, const struct http_credentials *credentials, int *stale) { if (o.proxy_auth == NULL) return 1; *stale = 0; if (credentials->scheme == AUTH_BASIC) { char *expected; int cmp; if (credentials->u.basic == NULL) return 0; /* We don't decode the received password, we encode the expected password and compare the encoded strings. */ expected = b64enc((unsigned char *) o.proxy_auth, strlen(o.proxy_auth)); cmp = strcmp(expected, credentials->u.basic); free(expected); return cmp == 0; } #if HAVE_HTTP_DIGEST else if (credentials->scheme == AUTH_DIGEST) { char *username, *password; char *proxy_auth; struct timeval nonce_tv, now; int nonce_age; int ret; /* Split up the proxy auth argument. */ proxy_auth = Strdup(o.proxy_auth); username = strtok(proxy_auth, ":"); password = strtok(NULL, ":"); if (password == NULL) { free(proxy_auth); return 0; } ret = http_digest_check_credentials(username, "Ncat", password, request->method, credentials); free(proxy_auth); if (!ret) return 0; /* The nonce checks out as one we issued and it matches what we expect given the credentials. Now check if it's too old. */ if (credentials->u.digest.nonce == NULL || http_digest_nonce_time(credentials->u.digest.nonce, &nonce_tv) == -1) return 0; gettimeofday(&now, NULL); if (TIMEVAL_AFTER(nonce_tv, now)) return 0; nonce_age = TIMEVAL_SEC_SUBTRACT(now, nonce_tv); if (nonce_age > HTTP_DIGEST_NONCE_EXPIRY) { if (o.verbose) loguser("Nonce is %d seconds old; rejecting.\n", nonce_age); *stale = 1; return 0; } /* To prevent replays, here we should additionally check against a list of recently used nonces, where "recently used nonce" is one that has been used to successfully authenticate within the last HTTP_DIGEST_NONCE_EXPIRY seconds. (Older than that and we don't need to keep it in the list, because the expiry test above will catch it. This isn't supported because the fork-and-process architecture of the proxy server makes it hard for us to change state in the parent process from here in the child. */ return 1; } #endif else { return 0; } }