1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker * TLS support for CUPS on Windows using the Security Support Provider
3*5e7646d2SAndroid Build Coastguard Worker * Interface (SSPI).
4*5e7646d2SAndroid Build Coastguard Worker *
5*5e7646d2SAndroid Build Coastguard Worker * Copyright 2010-2018 by Apple Inc.
6*5e7646d2SAndroid Build Coastguard Worker *
7*5e7646d2SAndroid Build Coastguard Worker * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
8*5e7646d2SAndroid Build Coastguard Worker */
9*5e7646d2SAndroid Build Coastguard Worker
10*5e7646d2SAndroid Build Coastguard Worker /**** This file is included from tls.c ****/
11*5e7646d2SAndroid Build Coastguard Worker
12*5e7646d2SAndroid Build Coastguard Worker /*
13*5e7646d2SAndroid Build Coastguard Worker * Include necessary headers...
14*5e7646d2SAndroid Build Coastguard Worker */
15*5e7646d2SAndroid Build Coastguard Worker
16*5e7646d2SAndroid Build Coastguard Worker #include "debug-private.h"
17*5e7646d2SAndroid Build Coastguard Worker
18*5e7646d2SAndroid Build Coastguard Worker
19*5e7646d2SAndroid Build Coastguard Worker /*
20*5e7646d2SAndroid Build Coastguard Worker * Include necessary libraries...
21*5e7646d2SAndroid Build Coastguard Worker */
22*5e7646d2SAndroid Build Coastguard Worker
23*5e7646d2SAndroid Build Coastguard Worker #pragma comment(lib, "Crypt32.lib")
24*5e7646d2SAndroid Build Coastguard Worker #pragma comment(lib, "Secur32.lib")
25*5e7646d2SAndroid Build Coastguard Worker #pragma comment(lib, "Ws2_32.lib")
26*5e7646d2SAndroid Build Coastguard Worker
27*5e7646d2SAndroid Build Coastguard Worker
28*5e7646d2SAndroid Build Coastguard Worker /*
29*5e7646d2SAndroid Build Coastguard Worker * Constants...
30*5e7646d2SAndroid Build Coastguard Worker */
31*5e7646d2SAndroid Build Coastguard Worker
32*5e7646d2SAndroid Build Coastguard Worker #ifndef SECURITY_FLAG_IGNORE_UNKNOWN_CA
33*5e7646d2SAndroid Build Coastguard Worker # define SECURITY_FLAG_IGNORE_UNKNOWN_CA 0x00000100 /* Untrusted root */
34*5e7646d2SAndroid Build Coastguard Worker #endif /* SECURITY_FLAG_IGNORE_UNKNOWN_CA */
35*5e7646d2SAndroid Build Coastguard Worker
36*5e7646d2SAndroid Build Coastguard Worker #ifndef SECURITY_FLAG_IGNORE_CERT_CN_INVALID
37*5e7646d2SAndroid Build Coastguard Worker # define SECURITY_FLAG_IGNORE_CERT_CN_INVALID 0x00001000 /* Common name does not match */
38*5e7646d2SAndroid Build Coastguard Worker #endif /* !SECURITY_FLAG_IGNORE_CERT_CN_INVALID */
39*5e7646d2SAndroid Build Coastguard Worker
40*5e7646d2SAndroid Build Coastguard Worker #ifndef SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
41*5e7646d2SAndroid Build Coastguard Worker # define SECURITY_FLAG_IGNORE_CERT_DATE_INVALID 0x00002000 /* Expired X509 Cert. */
42*5e7646d2SAndroid Build Coastguard Worker #endif /* !SECURITY_FLAG_IGNORE_CERT_DATE_INVALID */
43*5e7646d2SAndroid Build Coastguard Worker
44*5e7646d2SAndroid Build Coastguard Worker
45*5e7646d2SAndroid Build Coastguard Worker /*
46*5e7646d2SAndroid Build Coastguard Worker * Local globals...
47*5e7646d2SAndroid Build Coastguard Worker */
48*5e7646d2SAndroid Build Coastguard Worker
49*5e7646d2SAndroid Build Coastguard Worker static int tls_options = -1,/* Options for TLS connections */
50*5e7646d2SAndroid Build Coastguard Worker tls_min_version = _HTTP_TLS_1_0,
51*5e7646d2SAndroid Build Coastguard Worker tls_max_version = _HTTP_TLS_MAX;
52*5e7646d2SAndroid Build Coastguard Worker
53*5e7646d2SAndroid Build Coastguard Worker
54*5e7646d2SAndroid Build Coastguard Worker /*
55*5e7646d2SAndroid Build Coastguard Worker * Local functions...
56*5e7646d2SAndroid Build Coastguard Worker */
57*5e7646d2SAndroid Build Coastguard Worker
58*5e7646d2SAndroid Build Coastguard Worker static _http_sspi_t *http_sspi_alloc(void);
59*5e7646d2SAndroid Build Coastguard Worker static int http_sspi_client(http_t *http, const char *hostname);
60*5e7646d2SAndroid Build Coastguard Worker static PCCERT_CONTEXT http_sspi_create_credential(http_credential_t *cred);
61*5e7646d2SAndroid Build Coastguard Worker static BOOL http_sspi_find_credentials(http_t *http, const LPWSTR containerName, const char *common_name);
62*5e7646d2SAndroid Build Coastguard Worker static void http_sspi_free(_http_sspi_t *sspi);
63*5e7646d2SAndroid Build Coastguard Worker static BOOL http_sspi_make_credentials(_http_sspi_t *sspi, const LPWSTR containerName, const char *common_name, _http_mode_t mode, int years);
64*5e7646d2SAndroid Build Coastguard Worker static int http_sspi_server(http_t *http, const char *hostname);
65*5e7646d2SAndroid Build Coastguard Worker static void http_sspi_set_allows_any_root(_http_sspi_t *sspi, BOOL allow);
66*5e7646d2SAndroid Build Coastguard Worker static void http_sspi_set_allows_expired_certs(_http_sspi_t *sspi, BOOL allow);
67*5e7646d2SAndroid Build Coastguard Worker static const char *http_sspi_strerror(char *buffer, size_t bufsize, DWORD code);
68*5e7646d2SAndroid Build Coastguard Worker static DWORD http_sspi_verify(PCCERT_CONTEXT cert, const char *common_name, DWORD dwCertFlags);
69*5e7646d2SAndroid Build Coastguard Worker
70*5e7646d2SAndroid Build Coastguard Worker
71*5e7646d2SAndroid Build Coastguard Worker /*
72*5e7646d2SAndroid Build Coastguard Worker * 'cupsMakeServerCredentials()' - Make a self-signed certificate and private key pair.
73*5e7646d2SAndroid Build Coastguard Worker *
74*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 2.0/OS 10.10@
75*5e7646d2SAndroid Build Coastguard Worker */
76*5e7646d2SAndroid Build Coastguard Worker
77*5e7646d2SAndroid Build Coastguard Worker int /* O - 1 on success, 0 on failure */
cupsMakeServerCredentials(const char * path,const char * common_name,int num_alt_names,const char ** alt_names,time_t expiration_date)78*5e7646d2SAndroid Build Coastguard Worker cupsMakeServerCredentials(
79*5e7646d2SAndroid Build Coastguard Worker const char *path, /* I - Keychain path or @code NULL@ for default */
80*5e7646d2SAndroid Build Coastguard Worker const char *common_name, /* I - Common name */
81*5e7646d2SAndroid Build Coastguard Worker int num_alt_names, /* I - Number of subject alternate names */
82*5e7646d2SAndroid Build Coastguard Worker const char **alt_names, /* I - Subject Alternate Names */
83*5e7646d2SAndroid Build Coastguard Worker time_t expiration_date) /* I - Expiration date */
84*5e7646d2SAndroid Build Coastguard Worker {
85*5e7646d2SAndroid Build Coastguard Worker _http_sspi_t *sspi; /* SSPI data */
86*5e7646d2SAndroid Build Coastguard Worker int ret; /* Return value */
87*5e7646d2SAndroid Build Coastguard Worker
88*5e7646d2SAndroid Build Coastguard Worker
89*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("cupsMakeServerCredentials(path=\"%s\", common_name=\"%s\", num_alt_names=%d, alt_names=%p, expiration_date=%d)", path, common_name, num_alt_names, alt_names, (int)expiration_date));
90*5e7646d2SAndroid Build Coastguard Worker
91*5e7646d2SAndroid Build Coastguard Worker (void)path;
92*5e7646d2SAndroid Build Coastguard Worker (void)num_alt_names;
93*5e7646d2SAndroid Build Coastguard Worker (void)alt_names;
94*5e7646d2SAndroid Build Coastguard Worker
95*5e7646d2SAndroid Build Coastguard Worker sspi = http_sspi_alloc();
96*5e7646d2SAndroid Build Coastguard Worker ret = http_sspi_make_credentials(sspi, L"ServerContainer", common_name, _HTTP_MODE_SERVER, (int)((expiration_date - time(NULL) + 86399) / 86400 / 365));
97*5e7646d2SAndroid Build Coastguard Worker
98*5e7646d2SAndroid Build Coastguard Worker http_sspi_free(sspi);
99*5e7646d2SAndroid Build Coastguard Worker
100*5e7646d2SAndroid Build Coastguard Worker return (ret);
101*5e7646d2SAndroid Build Coastguard Worker }
102*5e7646d2SAndroid Build Coastguard Worker
103*5e7646d2SAndroid Build Coastguard Worker
104*5e7646d2SAndroid Build Coastguard Worker /*
105*5e7646d2SAndroid Build Coastguard Worker * 'cupsSetServerCredentials()' - Set the default server credentials.
106*5e7646d2SAndroid Build Coastguard Worker *
107*5e7646d2SAndroid Build Coastguard Worker * Note: The server credentials are used by all threads in the running process.
108*5e7646d2SAndroid Build Coastguard Worker * This function is threadsafe.
109*5e7646d2SAndroid Build Coastguard Worker *
110*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 2.0/OS 10.10@
111*5e7646d2SAndroid Build Coastguard Worker */
112*5e7646d2SAndroid Build Coastguard Worker
113*5e7646d2SAndroid Build Coastguard Worker int /* O - 1 on success, 0 on failure */
cupsSetServerCredentials(const char * path,const char * common_name,int auto_create)114*5e7646d2SAndroid Build Coastguard Worker cupsSetServerCredentials(
115*5e7646d2SAndroid Build Coastguard Worker const char *path, /* I - Keychain path or @code NULL@ for default */
116*5e7646d2SAndroid Build Coastguard Worker const char *common_name, /* I - Default common name for server */
117*5e7646d2SAndroid Build Coastguard Worker int auto_create) /* I - 1 = automatically create self-signed certificates */
118*5e7646d2SAndroid Build Coastguard Worker {
119*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("cupsSetServerCredentials(path=\"%s\", common_name=\"%s\", auto_create=%d)", path, common_name, auto_create));
120*5e7646d2SAndroid Build Coastguard Worker
121*5e7646d2SAndroid Build Coastguard Worker (void)path;
122*5e7646d2SAndroid Build Coastguard Worker (void)common_name;
123*5e7646d2SAndroid Build Coastguard Worker (void)auto_create;
124*5e7646d2SAndroid Build Coastguard Worker
125*5e7646d2SAndroid Build Coastguard Worker return (0);
126*5e7646d2SAndroid Build Coastguard Worker }
127*5e7646d2SAndroid Build Coastguard Worker
128*5e7646d2SAndroid Build Coastguard Worker
129*5e7646d2SAndroid Build Coastguard Worker /*
130*5e7646d2SAndroid Build Coastguard Worker * 'httpCopyCredentials()' - Copy the credentials associated with the peer in
131*5e7646d2SAndroid Build Coastguard Worker * an encrypted connection.
132*5e7646d2SAndroid Build Coastguard Worker *
133*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 1.5/macOS 10.7@
134*5e7646d2SAndroid Build Coastguard Worker */
135*5e7646d2SAndroid Build Coastguard Worker
136*5e7646d2SAndroid Build Coastguard Worker int /* O - Status of call (0 = success) */
httpCopyCredentials(http_t * http,cups_array_t ** credentials)137*5e7646d2SAndroid Build Coastguard Worker httpCopyCredentials(
138*5e7646d2SAndroid Build Coastguard Worker http_t *http, /* I - Connection to server */
139*5e7646d2SAndroid Build Coastguard Worker cups_array_t **credentials) /* O - Array of credentials */
140*5e7646d2SAndroid Build Coastguard Worker {
141*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("httpCopyCredentials(http=%p, credentials=%p)", http, credentials));
142*5e7646d2SAndroid Build Coastguard Worker
143*5e7646d2SAndroid Build Coastguard Worker if (!http || !http->tls || !http->tls->remoteCert || !credentials)
144*5e7646d2SAndroid Build Coastguard Worker {
145*5e7646d2SAndroid Build Coastguard Worker if (credentials)
146*5e7646d2SAndroid Build Coastguard Worker *credentials = NULL;
147*5e7646d2SAndroid Build Coastguard Worker
148*5e7646d2SAndroid Build Coastguard Worker return (-1);
149*5e7646d2SAndroid Build Coastguard Worker }
150*5e7646d2SAndroid Build Coastguard Worker
151*5e7646d2SAndroid Build Coastguard Worker *credentials = cupsArrayNew(NULL, NULL);
152*5e7646d2SAndroid Build Coastguard Worker httpAddCredential(*credentials, http->tls->remoteCert->pbCertEncoded, http->tls->remoteCert->cbCertEncoded);
153*5e7646d2SAndroid Build Coastguard Worker
154*5e7646d2SAndroid Build Coastguard Worker return (0);
155*5e7646d2SAndroid Build Coastguard Worker }
156*5e7646d2SAndroid Build Coastguard Worker
157*5e7646d2SAndroid Build Coastguard Worker
158*5e7646d2SAndroid Build Coastguard Worker /*
159*5e7646d2SAndroid Build Coastguard Worker * '_httpCreateCredentials()' - Create credentials in the internal format.
160*5e7646d2SAndroid Build Coastguard Worker */
161*5e7646d2SAndroid Build Coastguard Worker
162*5e7646d2SAndroid Build Coastguard Worker http_tls_credentials_t /* O - Internal credentials */
_httpCreateCredentials(cups_array_t * credentials)163*5e7646d2SAndroid Build Coastguard Worker _httpCreateCredentials(
164*5e7646d2SAndroid Build Coastguard Worker cups_array_t *credentials) /* I - Array of credentials */
165*5e7646d2SAndroid Build Coastguard Worker {
166*5e7646d2SAndroid Build Coastguard Worker return (http_sspi_create_credential((http_credential_t *)cupsArrayFirst(credentials)));
167*5e7646d2SAndroid Build Coastguard Worker }
168*5e7646d2SAndroid Build Coastguard Worker
169*5e7646d2SAndroid Build Coastguard Worker
170*5e7646d2SAndroid Build Coastguard Worker /*
171*5e7646d2SAndroid Build Coastguard Worker * 'httpCredentialsAreValidForName()' - Return whether the credentials are valid for the given name.
172*5e7646d2SAndroid Build Coastguard Worker *
173*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 2.0/OS 10.10@
174*5e7646d2SAndroid Build Coastguard Worker */
175*5e7646d2SAndroid Build Coastguard Worker
176*5e7646d2SAndroid Build Coastguard Worker int /* O - 1 if valid, 0 otherwise */
httpCredentialsAreValidForName(cups_array_t * credentials,const char * common_name)177*5e7646d2SAndroid Build Coastguard Worker httpCredentialsAreValidForName(
178*5e7646d2SAndroid Build Coastguard Worker cups_array_t *credentials, /* I - Credentials */
179*5e7646d2SAndroid Build Coastguard Worker const char *common_name) /* I - Name to check */
180*5e7646d2SAndroid Build Coastguard Worker {
181*5e7646d2SAndroid Build Coastguard Worker int valid = 1; /* Valid name? */
182*5e7646d2SAndroid Build Coastguard Worker PCCERT_CONTEXT cert = http_sspi_create_credential((http_credential_t *)cupsArrayFirst(credentials));
183*5e7646d2SAndroid Build Coastguard Worker /* Certificate */
184*5e7646d2SAndroid Build Coastguard Worker char cert_name[1024]; /* Name from certificate */
185*5e7646d2SAndroid Build Coastguard Worker
186*5e7646d2SAndroid Build Coastguard Worker
187*5e7646d2SAndroid Build Coastguard Worker if (cert)
188*5e7646d2SAndroid Build Coastguard Worker {
189*5e7646d2SAndroid Build Coastguard Worker if (CertNameToStrA(X509_ASN_ENCODING, &(cert->pCertInfo->Subject), CERT_SIMPLE_NAME_STR, cert_name, sizeof(cert_name)))
190*5e7646d2SAndroid Build Coastguard Worker {
191*5e7646d2SAndroid Build Coastguard Worker /*
192*5e7646d2SAndroid Build Coastguard Worker * Extract common name at end...
193*5e7646d2SAndroid Build Coastguard Worker */
194*5e7646d2SAndroid Build Coastguard Worker
195*5e7646d2SAndroid Build Coastguard Worker char *ptr = strrchr(cert_name, ',');
196*5e7646d2SAndroid Build Coastguard Worker if (ptr && ptr[1])
197*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(cert_name, ptr + 2);
198*5e7646d2SAndroid Build Coastguard Worker }
199*5e7646d2SAndroid Build Coastguard Worker else
200*5e7646d2SAndroid Build Coastguard Worker strlcpy(cert_name, "unknown", sizeof(cert_name));
201*5e7646d2SAndroid Build Coastguard Worker
202*5e7646d2SAndroid Build Coastguard Worker CertFreeCertificateContext(cert);
203*5e7646d2SAndroid Build Coastguard Worker }
204*5e7646d2SAndroid Build Coastguard Worker else
205*5e7646d2SAndroid Build Coastguard Worker strlcpy(cert_name, "unknown", sizeof(cert_name));
206*5e7646d2SAndroid Build Coastguard Worker
207*5e7646d2SAndroid Build Coastguard Worker /*
208*5e7646d2SAndroid Build Coastguard Worker * Compare the common names...
209*5e7646d2SAndroid Build Coastguard Worker */
210*5e7646d2SAndroid Build Coastguard Worker
211*5e7646d2SAndroid Build Coastguard Worker if (_cups_strcasecmp(common_name, cert_name))
212*5e7646d2SAndroid Build Coastguard Worker {
213*5e7646d2SAndroid Build Coastguard Worker /*
214*5e7646d2SAndroid Build Coastguard Worker * Not an exact match for the common name, check for wildcard certs...
215*5e7646d2SAndroid Build Coastguard Worker */
216*5e7646d2SAndroid Build Coastguard Worker
217*5e7646d2SAndroid Build Coastguard Worker const char *domain = strchr(common_name, '.');
218*5e7646d2SAndroid Build Coastguard Worker /* Domain in common name */
219*5e7646d2SAndroid Build Coastguard Worker
220*5e7646d2SAndroid Build Coastguard Worker if (strncmp(cert_name, "*.", 2) || !domain || _cups_strcasecmp(domain, cert_name + 1))
221*5e7646d2SAndroid Build Coastguard Worker {
222*5e7646d2SAndroid Build Coastguard Worker /*
223*5e7646d2SAndroid Build Coastguard Worker * Not a wildcard match.
224*5e7646d2SAndroid Build Coastguard Worker */
225*5e7646d2SAndroid Build Coastguard Worker
226*5e7646d2SAndroid Build Coastguard Worker /* TODO: Check subject alternate names */
227*5e7646d2SAndroid Build Coastguard Worker valid = 0;
228*5e7646d2SAndroid Build Coastguard Worker }
229*5e7646d2SAndroid Build Coastguard Worker }
230*5e7646d2SAndroid Build Coastguard Worker
231*5e7646d2SAndroid Build Coastguard Worker return (valid);
232*5e7646d2SAndroid Build Coastguard Worker }
233*5e7646d2SAndroid Build Coastguard Worker
234*5e7646d2SAndroid Build Coastguard Worker
235*5e7646d2SAndroid Build Coastguard Worker /*
236*5e7646d2SAndroid Build Coastguard Worker * 'httpCredentialsGetTrust()' - Return the trust of credentials.
237*5e7646d2SAndroid Build Coastguard Worker *
238*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 2.0/OS 10.10@
239*5e7646d2SAndroid Build Coastguard Worker */
240*5e7646d2SAndroid Build Coastguard Worker
241*5e7646d2SAndroid Build Coastguard Worker http_trust_t /* O - Level of trust */
httpCredentialsGetTrust(cups_array_t * credentials,const char * common_name)242*5e7646d2SAndroid Build Coastguard Worker httpCredentialsGetTrust(
243*5e7646d2SAndroid Build Coastguard Worker cups_array_t *credentials, /* I - Credentials */
244*5e7646d2SAndroid Build Coastguard Worker const char *common_name) /* I - Common name for trust lookup */
245*5e7646d2SAndroid Build Coastguard Worker {
246*5e7646d2SAndroid Build Coastguard Worker http_trust_t trust = HTTP_TRUST_OK; /* Level of trust */
247*5e7646d2SAndroid Build Coastguard Worker PCCERT_CONTEXT cert = NULL; /* Certificate to validate */
248*5e7646d2SAndroid Build Coastguard Worker DWORD certFlags = 0; /* Cert verification flags */
249*5e7646d2SAndroid Build Coastguard Worker _cups_globals_t *cg = _cupsGlobals(); /* Per-thread global data */
250*5e7646d2SAndroid Build Coastguard Worker
251*5e7646d2SAndroid Build Coastguard Worker
252*5e7646d2SAndroid Build Coastguard Worker if (!common_name)
253*5e7646d2SAndroid Build Coastguard Worker return (HTTP_TRUST_UNKNOWN);
254*5e7646d2SAndroid Build Coastguard Worker
255*5e7646d2SAndroid Build Coastguard Worker cert = http_sspi_create_credential((http_credential_t *)cupsArrayFirst(credentials));
256*5e7646d2SAndroid Build Coastguard Worker if (!cert)
257*5e7646d2SAndroid Build Coastguard Worker return (HTTP_TRUST_UNKNOWN);
258*5e7646d2SAndroid Build Coastguard Worker
259*5e7646d2SAndroid Build Coastguard Worker if (cg->any_root < 0)
260*5e7646d2SAndroid Build Coastguard Worker _cupsSetDefaults();
261*5e7646d2SAndroid Build Coastguard Worker
262*5e7646d2SAndroid Build Coastguard Worker if (cg->any_root)
263*5e7646d2SAndroid Build Coastguard Worker certFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
264*5e7646d2SAndroid Build Coastguard Worker
265*5e7646d2SAndroid Build Coastguard Worker if (cg->expired_certs)
266*5e7646d2SAndroid Build Coastguard Worker certFlags |= SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
267*5e7646d2SAndroid Build Coastguard Worker
268*5e7646d2SAndroid Build Coastguard Worker if (!cg->validate_certs)
269*5e7646d2SAndroid Build Coastguard Worker certFlags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
270*5e7646d2SAndroid Build Coastguard Worker
271*5e7646d2SAndroid Build Coastguard Worker if (http_sspi_verify(cert, common_name, certFlags) != SEC_E_OK)
272*5e7646d2SAndroid Build Coastguard Worker trust = HTTP_TRUST_INVALID;
273*5e7646d2SAndroid Build Coastguard Worker
274*5e7646d2SAndroid Build Coastguard Worker CertFreeCertificateContext(cert);
275*5e7646d2SAndroid Build Coastguard Worker
276*5e7646d2SAndroid Build Coastguard Worker return (trust);
277*5e7646d2SAndroid Build Coastguard Worker }
278*5e7646d2SAndroid Build Coastguard Worker
279*5e7646d2SAndroid Build Coastguard Worker
280*5e7646d2SAndroid Build Coastguard Worker /*
281*5e7646d2SAndroid Build Coastguard Worker * 'httpCredentialsGetExpiration()' - Return the expiration date of the credentials.
282*5e7646d2SAndroid Build Coastguard Worker *
283*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 2.0/OS 10.10@
284*5e7646d2SAndroid Build Coastguard Worker */
285*5e7646d2SAndroid Build Coastguard Worker
286*5e7646d2SAndroid Build Coastguard Worker time_t /* O - Expiration date of credentials */
httpCredentialsGetExpiration(cups_array_t * credentials)287*5e7646d2SAndroid Build Coastguard Worker httpCredentialsGetExpiration(
288*5e7646d2SAndroid Build Coastguard Worker cups_array_t *credentials) /* I - Credentials */
289*5e7646d2SAndroid Build Coastguard Worker {
290*5e7646d2SAndroid Build Coastguard Worker time_t expiration_date = 0; /* Expiration data of credentials */
291*5e7646d2SAndroid Build Coastguard Worker PCCERT_CONTEXT cert = http_sspi_create_credential((http_credential_t *)cupsArrayFirst(credentials));
292*5e7646d2SAndroid Build Coastguard Worker /* Certificate */
293*5e7646d2SAndroid Build Coastguard Worker
294*5e7646d2SAndroid Build Coastguard Worker if (cert)
295*5e7646d2SAndroid Build Coastguard Worker {
296*5e7646d2SAndroid Build Coastguard Worker SYSTEMTIME systime; /* System time */
297*5e7646d2SAndroid Build Coastguard Worker struct tm tm; /* UNIX date/time */
298*5e7646d2SAndroid Build Coastguard Worker
299*5e7646d2SAndroid Build Coastguard Worker FileTimeToSystemTime(&(cert->pCertInfo->NotAfter), &systime);
300*5e7646d2SAndroid Build Coastguard Worker
301*5e7646d2SAndroid Build Coastguard Worker tm.tm_year = systime.wYear - 1900;
302*5e7646d2SAndroid Build Coastguard Worker tm.tm_mon = systime.wMonth - 1;
303*5e7646d2SAndroid Build Coastguard Worker tm.tm_mday = systime.wDay;
304*5e7646d2SAndroid Build Coastguard Worker tm.tm_hour = systime.wHour;
305*5e7646d2SAndroid Build Coastguard Worker tm.tm_min = systime.wMinute;
306*5e7646d2SAndroid Build Coastguard Worker tm.tm_sec = systime.wSecond;
307*5e7646d2SAndroid Build Coastguard Worker
308*5e7646d2SAndroid Build Coastguard Worker expiration_date = mktime(&tm);
309*5e7646d2SAndroid Build Coastguard Worker
310*5e7646d2SAndroid Build Coastguard Worker CertFreeCertificateContext(cert);
311*5e7646d2SAndroid Build Coastguard Worker }
312*5e7646d2SAndroid Build Coastguard Worker
313*5e7646d2SAndroid Build Coastguard Worker return (expiration_date);
314*5e7646d2SAndroid Build Coastguard Worker }
315*5e7646d2SAndroid Build Coastguard Worker
316*5e7646d2SAndroid Build Coastguard Worker
317*5e7646d2SAndroid Build Coastguard Worker /*
318*5e7646d2SAndroid Build Coastguard Worker * 'httpCredentialsString()' - Return a string representing the credentials.
319*5e7646d2SAndroid Build Coastguard Worker *
320*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 2.0/OS 10.10@
321*5e7646d2SAndroid Build Coastguard Worker */
322*5e7646d2SAndroid Build Coastguard Worker
323*5e7646d2SAndroid Build Coastguard Worker size_t /* O - Total size of credentials string */
httpCredentialsString(cups_array_t * credentials,char * buffer,size_t bufsize)324*5e7646d2SAndroid Build Coastguard Worker httpCredentialsString(
325*5e7646d2SAndroid Build Coastguard Worker cups_array_t *credentials, /* I - Credentials */
326*5e7646d2SAndroid Build Coastguard Worker char *buffer, /* I - Buffer or @code NULL@ */
327*5e7646d2SAndroid Build Coastguard Worker size_t bufsize) /* I - Size of buffer */
328*5e7646d2SAndroid Build Coastguard Worker {
329*5e7646d2SAndroid Build Coastguard Worker http_credential_t *first = (http_credential_t *)cupsArrayFirst(credentials);
330*5e7646d2SAndroid Build Coastguard Worker /* First certificate */
331*5e7646d2SAndroid Build Coastguard Worker PCCERT_CONTEXT cert; /* Certificate */
332*5e7646d2SAndroid Build Coastguard Worker
333*5e7646d2SAndroid Build Coastguard Worker
334*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("httpCredentialsString(credentials=%p, buffer=%p, bufsize=" CUPS_LLFMT ")", credentials, buffer, CUPS_LLCAST bufsize));
335*5e7646d2SAndroid Build Coastguard Worker
336*5e7646d2SAndroid Build Coastguard Worker if (!buffer)
337*5e7646d2SAndroid Build Coastguard Worker return (0);
338*5e7646d2SAndroid Build Coastguard Worker
339*5e7646d2SAndroid Build Coastguard Worker if (buffer && bufsize > 0)
340*5e7646d2SAndroid Build Coastguard Worker *buffer = '\0';
341*5e7646d2SAndroid Build Coastguard Worker
342*5e7646d2SAndroid Build Coastguard Worker cert = http_sspi_create_credential(first);
343*5e7646d2SAndroid Build Coastguard Worker
344*5e7646d2SAndroid Build Coastguard Worker if (cert)
345*5e7646d2SAndroid Build Coastguard Worker {
346*5e7646d2SAndroid Build Coastguard Worker char cert_name[256]; /* Common name */
347*5e7646d2SAndroid Build Coastguard Worker SYSTEMTIME systime; /* System time */
348*5e7646d2SAndroid Build Coastguard Worker struct tm tm; /* UNIX date/time */
349*5e7646d2SAndroid Build Coastguard Worker time_t expiration; /* Expiration date of cert */
350*5e7646d2SAndroid Build Coastguard Worker unsigned char md5_digest[16]; /* MD5 result */
351*5e7646d2SAndroid Build Coastguard Worker
352*5e7646d2SAndroid Build Coastguard Worker FileTimeToSystemTime(&(cert->pCertInfo->NotAfter), &systime);
353*5e7646d2SAndroid Build Coastguard Worker
354*5e7646d2SAndroid Build Coastguard Worker tm.tm_year = systime.wYear - 1900;
355*5e7646d2SAndroid Build Coastguard Worker tm.tm_mon = systime.wMonth - 1;
356*5e7646d2SAndroid Build Coastguard Worker tm.tm_mday = systime.wDay;
357*5e7646d2SAndroid Build Coastguard Worker tm.tm_hour = systime.wHour;
358*5e7646d2SAndroid Build Coastguard Worker tm.tm_min = systime.wMinute;
359*5e7646d2SAndroid Build Coastguard Worker tm.tm_sec = systime.wSecond;
360*5e7646d2SAndroid Build Coastguard Worker
361*5e7646d2SAndroid Build Coastguard Worker expiration = mktime(&tm);
362*5e7646d2SAndroid Build Coastguard Worker
363*5e7646d2SAndroid Build Coastguard Worker if (CertNameToStrA(X509_ASN_ENCODING, &(cert->pCertInfo->Subject), CERT_SIMPLE_NAME_STR, cert_name, sizeof(cert_name)))
364*5e7646d2SAndroid Build Coastguard Worker {
365*5e7646d2SAndroid Build Coastguard Worker /*
366*5e7646d2SAndroid Build Coastguard Worker * Extract common name at end...
367*5e7646d2SAndroid Build Coastguard Worker */
368*5e7646d2SAndroid Build Coastguard Worker
369*5e7646d2SAndroid Build Coastguard Worker char *ptr = strrchr(cert_name, ',');
370*5e7646d2SAndroid Build Coastguard Worker if (ptr && ptr[1])
371*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(cert_name, ptr + 2);
372*5e7646d2SAndroid Build Coastguard Worker }
373*5e7646d2SAndroid Build Coastguard Worker else
374*5e7646d2SAndroid Build Coastguard Worker strlcpy(cert_name, "unknown", sizeof(cert_name));
375*5e7646d2SAndroid Build Coastguard Worker
376*5e7646d2SAndroid Build Coastguard Worker cupsHashData("md5", first->data, first->datalen, md5_digest, sizeof(md5_digest));
377*5e7646d2SAndroid Build Coastguard Worker
378*5e7646d2SAndroid Build Coastguard Worker snprintf(buffer, bufsize, "%s / %s / %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", cert_name, httpGetDateString(expiration), md5_digest[0], md5_digest[1], md5_digest[2], md5_digest[3], md5_digest[4], md5_digest[5], md5_digest[6], md5_digest[7], md5_digest[8], md5_digest[9], md5_digest[10], md5_digest[11], md5_digest[12], md5_digest[13], md5_digest[14], md5_digest[15]);
379*5e7646d2SAndroid Build Coastguard Worker
380*5e7646d2SAndroid Build Coastguard Worker CertFreeCertificateContext(cert);
381*5e7646d2SAndroid Build Coastguard Worker }
382*5e7646d2SAndroid Build Coastguard Worker
383*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1httpCredentialsString: Returning \"%s\".", buffer));
384*5e7646d2SAndroid Build Coastguard Worker
385*5e7646d2SAndroid Build Coastguard Worker return (strlen(buffer));
386*5e7646d2SAndroid Build Coastguard Worker }
387*5e7646d2SAndroid Build Coastguard Worker
388*5e7646d2SAndroid Build Coastguard Worker
389*5e7646d2SAndroid Build Coastguard Worker /*
390*5e7646d2SAndroid Build Coastguard Worker * '_httpFreeCredentials()' - Free internal credentials.
391*5e7646d2SAndroid Build Coastguard Worker */
392*5e7646d2SAndroid Build Coastguard Worker
393*5e7646d2SAndroid Build Coastguard Worker void
_httpFreeCredentials(http_tls_credentials_t credentials)394*5e7646d2SAndroid Build Coastguard Worker _httpFreeCredentials(
395*5e7646d2SAndroid Build Coastguard Worker http_tls_credentials_t credentials) /* I - Internal credentials */
396*5e7646d2SAndroid Build Coastguard Worker {
397*5e7646d2SAndroid Build Coastguard Worker if (!credentials)
398*5e7646d2SAndroid Build Coastguard Worker return;
399*5e7646d2SAndroid Build Coastguard Worker
400*5e7646d2SAndroid Build Coastguard Worker CertFreeCertificateContext(credentials);
401*5e7646d2SAndroid Build Coastguard Worker }
402*5e7646d2SAndroid Build Coastguard Worker
403*5e7646d2SAndroid Build Coastguard Worker
404*5e7646d2SAndroid Build Coastguard Worker /*
405*5e7646d2SAndroid Build Coastguard Worker * 'httpLoadCredentials()' - Load X.509 credentials from a keychain file.
406*5e7646d2SAndroid Build Coastguard Worker *
407*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 2.0/OS 10.10@
408*5e7646d2SAndroid Build Coastguard Worker */
409*5e7646d2SAndroid Build Coastguard Worker
410*5e7646d2SAndroid Build Coastguard Worker int /* O - 0 on success, -1 on error */
httpLoadCredentials(const char * path,cups_array_t ** credentials,const char * common_name)411*5e7646d2SAndroid Build Coastguard Worker httpLoadCredentials(
412*5e7646d2SAndroid Build Coastguard Worker const char *path, /* I - Keychain path or @code NULL@ for default */
413*5e7646d2SAndroid Build Coastguard Worker cups_array_t **credentials, /* IO - Credentials */
414*5e7646d2SAndroid Build Coastguard Worker const char *common_name) /* I - Common name for credentials */
415*5e7646d2SAndroid Build Coastguard Worker {
416*5e7646d2SAndroid Build Coastguard Worker HCERTSTORE store = NULL; /* Certificate store */
417*5e7646d2SAndroid Build Coastguard Worker PCCERT_CONTEXT storedContext = NULL; /* Context created from the store */
418*5e7646d2SAndroid Build Coastguard Worker DWORD dwSize = 0; /* 32 bit size */
419*5e7646d2SAndroid Build Coastguard Worker PBYTE p = NULL; /* Temporary storage */
420*5e7646d2SAndroid Build Coastguard Worker HCRYPTPROV hProv = (HCRYPTPROV)NULL;
421*5e7646d2SAndroid Build Coastguard Worker /* Handle to a CSP */
422*5e7646d2SAndroid Build Coastguard Worker CERT_NAME_BLOB sib; /* Arbitrary array of bytes */
423*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
424*5e7646d2SAndroid Build Coastguard Worker char error[1024]; /* Error message buffer */
425*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
426*5e7646d2SAndroid Build Coastguard Worker
427*5e7646d2SAndroid Build Coastguard Worker
428*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("httpLoadCredentials(path=\"%s\", credentials=%p, common_name=\"%s\")", path, credentials, common_name));
429*5e7646d2SAndroid Build Coastguard Worker
430*5e7646d2SAndroid Build Coastguard Worker (void)path;
431*5e7646d2SAndroid Build Coastguard Worker
432*5e7646d2SAndroid Build Coastguard Worker if (credentials)
433*5e7646d2SAndroid Build Coastguard Worker {
434*5e7646d2SAndroid Build Coastguard Worker *credentials = NULL;
435*5e7646d2SAndroid Build Coastguard Worker }
436*5e7646d2SAndroid Build Coastguard Worker else
437*5e7646d2SAndroid Build Coastguard Worker {
438*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("1httpLoadCredentials: NULL credentials pointer, returning -1.");
439*5e7646d2SAndroid Build Coastguard Worker return (-1);
440*5e7646d2SAndroid Build Coastguard Worker }
441*5e7646d2SAndroid Build Coastguard Worker
442*5e7646d2SAndroid Build Coastguard Worker if (!common_name)
443*5e7646d2SAndroid Build Coastguard Worker {
444*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("1httpLoadCredentials: Bad common name, returning -1.");
445*5e7646d2SAndroid Build Coastguard Worker return (-1);
446*5e7646d2SAndroid Build Coastguard Worker }
447*5e7646d2SAndroid Build Coastguard Worker
448*5e7646d2SAndroid Build Coastguard Worker if (!CryptAcquireContextW(&hProv, L"RememberedContainer", MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_MACHINE_KEYSET))
449*5e7646d2SAndroid Build Coastguard Worker {
450*5e7646d2SAndroid Build Coastguard Worker if (GetLastError() == NTE_EXISTS)
451*5e7646d2SAndroid Build Coastguard Worker {
452*5e7646d2SAndroid Build Coastguard Worker if (!CryptAcquireContextW(&hProv, L"RememberedContainer", MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET))
453*5e7646d2SAndroid Build Coastguard Worker {
454*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1httpLoadCredentials: CryptAcquireContext failed: %s", http_sspi_strerror(error, sizeof(error), GetLastError())));
455*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
456*5e7646d2SAndroid Build Coastguard Worker }
457*5e7646d2SAndroid Build Coastguard Worker }
458*5e7646d2SAndroid Build Coastguard Worker }
459*5e7646d2SAndroid Build Coastguard Worker
460*5e7646d2SAndroid Build Coastguard Worker store = CertOpenStore(CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING|PKCS_7_ASN_ENCODING, hProv, CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_NO_CRYPT_RELEASE_FLAG | CERT_STORE_OPEN_EXISTING_FLAG, L"MY");
461*5e7646d2SAndroid Build Coastguard Worker
462*5e7646d2SAndroid Build Coastguard Worker if (!store)
463*5e7646d2SAndroid Build Coastguard Worker {
464*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1httpLoadCredentials: CertOpenSystemStore failed: %s", http_sspi_strerror(error, sizeof(error), GetLastError())));
465*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
466*5e7646d2SAndroid Build Coastguard Worker }
467*5e7646d2SAndroid Build Coastguard Worker
468*5e7646d2SAndroid Build Coastguard Worker dwSize = 0;
469*5e7646d2SAndroid Build Coastguard Worker
470*5e7646d2SAndroid Build Coastguard Worker if (!CertStrToNameA(X509_ASN_ENCODING, common_name, CERT_OID_NAME_STR, NULL, NULL, &dwSize, NULL))
471*5e7646d2SAndroid Build Coastguard Worker {
472*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1httpLoadCredentials: CertStrToName failed: %s", http_sspi_strerror(error, sizeof(error), GetLastError())));
473*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
474*5e7646d2SAndroid Build Coastguard Worker }
475*5e7646d2SAndroid Build Coastguard Worker
476*5e7646d2SAndroid Build Coastguard Worker p = (PBYTE)malloc(dwSize);
477*5e7646d2SAndroid Build Coastguard Worker
478*5e7646d2SAndroid Build Coastguard Worker if (!p)
479*5e7646d2SAndroid Build Coastguard Worker {
480*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1httpLoadCredentials: malloc failed for %d bytes.", dwSize));
481*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
482*5e7646d2SAndroid Build Coastguard Worker }
483*5e7646d2SAndroid Build Coastguard Worker
484*5e7646d2SAndroid Build Coastguard Worker if (!CertStrToNameA(X509_ASN_ENCODING, common_name, CERT_OID_NAME_STR, NULL, p, &dwSize, NULL))
485*5e7646d2SAndroid Build Coastguard Worker {
486*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1httpLoadCredentials: CertStrToName failed: %s", http_sspi_strerror(error, sizeof(error), GetLastError())));
487*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
488*5e7646d2SAndroid Build Coastguard Worker }
489*5e7646d2SAndroid Build Coastguard Worker
490*5e7646d2SAndroid Build Coastguard Worker sib.cbData = dwSize;
491*5e7646d2SAndroid Build Coastguard Worker sib.pbData = p;
492*5e7646d2SAndroid Build Coastguard Worker
493*5e7646d2SAndroid Build Coastguard Worker storedContext = CertFindCertificateInStore(store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_NAME, &sib, NULL);
494*5e7646d2SAndroid Build Coastguard Worker
495*5e7646d2SAndroid Build Coastguard Worker if (!storedContext)
496*5e7646d2SAndroid Build Coastguard Worker {
497*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1httpLoadCredentials: Unable to find credentials for \"%s\".", common_name));
498*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
499*5e7646d2SAndroid Build Coastguard Worker }
500*5e7646d2SAndroid Build Coastguard Worker
501*5e7646d2SAndroid Build Coastguard Worker *credentials = cupsArrayNew(NULL, NULL);
502*5e7646d2SAndroid Build Coastguard Worker httpAddCredential(*credentials, storedContext->pbCertEncoded, storedContext->cbCertEncoded);
503*5e7646d2SAndroid Build Coastguard Worker
504*5e7646d2SAndroid Build Coastguard Worker cleanup:
505*5e7646d2SAndroid Build Coastguard Worker
506*5e7646d2SAndroid Build Coastguard Worker /*
507*5e7646d2SAndroid Build Coastguard Worker * Cleanup
508*5e7646d2SAndroid Build Coastguard Worker */
509*5e7646d2SAndroid Build Coastguard Worker
510*5e7646d2SAndroid Build Coastguard Worker if (storedContext)
511*5e7646d2SAndroid Build Coastguard Worker CertFreeCertificateContext(storedContext);
512*5e7646d2SAndroid Build Coastguard Worker
513*5e7646d2SAndroid Build Coastguard Worker if (p)
514*5e7646d2SAndroid Build Coastguard Worker free(p);
515*5e7646d2SAndroid Build Coastguard Worker
516*5e7646d2SAndroid Build Coastguard Worker if (store)
517*5e7646d2SAndroid Build Coastguard Worker CertCloseStore(store, 0);
518*5e7646d2SAndroid Build Coastguard Worker
519*5e7646d2SAndroid Build Coastguard Worker if (hProv)
520*5e7646d2SAndroid Build Coastguard Worker CryptReleaseContext(hProv, 0);
521*5e7646d2SAndroid Build Coastguard Worker
522*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1httpLoadCredentials: Returning %d.", *credentials ? 0 : -1));
523*5e7646d2SAndroid Build Coastguard Worker
524*5e7646d2SAndroid Build Coastguard Worker return (*credentials ? 0 : -1);
525*5e7646d2SAndroid Build Coastguard Worker }
526*5e7646d2SAndroid Build Coastguard Worker
527*5e7646d2SAndroid Build Coastguard Worker
528*5e7646d2SAndroid Build Coastguard Worker /*
529*5e7646d2SAndroid Build Coastguard Worker * 'httpSaveCredentials()' - Save X.509 credentials to a keychain file.
530*5e7646d2SAndroid Build Coastguard Worker *
531*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 2.0/OS 10.10@
532*5e7646d2SAndroid Build Coastguard Worker */
533*5e7646d2SAndroid Build Coastguard Worker
534*5e7646d2SAndroid Build Coastguard Worker int /* O - -1 on error, 0 on success */
httpSaveCredentials(const char * path,cups_array_t * credentials,const char * common_name)535*5e7646d2SAndroid Build Coastguard Worker httpSaveCredentials(
536*5e7646d2SAndroid Build Coastguard Worker const char *path, /* I - Keychain path or @code NULL@ for default */
537*5e7646d2SAndroid Build Coastguard Worker cups_array_t *credentials, /* I - Credentials */
538*5e7646d2SAndroid Build Coastguard Worker const char *common_name) /* I - Common name for credentials */
539*5e7646d2SAndroid Build Coastguard Worker {
540*5e7646d2SAndroid Build Coastguard Worker HCERTSTORE store = NULL; /* Certificate store */
541*5e7646d2SAndroid Build Coastguard Worker PCCERT_CONTEXT storedContext = NULL; /* Context created from the store */
542*5e7646d2SAndroid Build Coastguard Worker PCCERT_CONTEXT createdContext = NULL; /* Context created by us */
543*5e7646d2SAndroid Build Coastguard Worker DWORD dwSize = 0; /* 32 bit size */
544*5e7646d2SAndroid Build Coastguard Worker PBYTE p = NULL; /* Temporary storage */
545*5e7646d2SAndroid Build Coastguard Worker HCRYPTPROV hProv = (HCRYPTPROV)NULL;
546*5e7646d2SAndroid Build Coastguard Worker /* Handle to a CSP */
547*5e7646d2SAndroid Build Coastguard Worker CRYPT_KEY_PROV_INFO ckp; /* Handle to crypto key */
548*5e7646d2SAndroid Build Coastguard Worker int ret = -1; /* Return value */
549*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
550*5e7646d2SAndroid Build Coastguard Worker char error[1024]; /* Error message buffer */
551*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
552*5e7646d2SAndroid Build Coastguard Worker
553*5e7646d2SAndroid Build Coastguard Worker
554*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("httpSaveCredentials(path=\"%s\", credentials=%p, common_name=\"%s\")", path, credentials, common_name));
555*5e7646d2SAndroid Build Coastguard Worker
556*5e7646d2SAndroid Build Coastguard Worker (void)path;
557*5e7646d2SAndroid Build Coastguard Worker
558*5e7646d2SAndroid Build Coastguard Worker if (!common_name)
559*5e7646d2SAndroid Build Coastguard Worker {
560*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("1httpSaveCredentials: Bad common name, returning -1.");
561*5e7646d2SAndroid Build Coastguard Worker return (-1);
562*5e7646d2SAndroid Build Coastguard Worker }
563*5e7646d2SAndroid Build Coastguard Worker
564*5e7646d2SAndroid Build Coastguard Worker createdContext = http_sspi_create_credential((http_credential_t *)cupsArrayFirst(credentials));
565*5e7646d2SAndroid Build Coastguard Worker if (!createdContext)
566*5e7646d2SAndroid Build Coastguard Worker {
567*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("1httpSaveCredentials: Bad credentials, returning -1.");
568*5e7646d2SAndroid Build Coastguard Worker return (-1);
569*5e7646d2SAndroid Build Coastguard Worker }
570*5e7646d2SAndroid Build Coastguard Worker
571*5e7646d2SAndroid Build Coastguard Worker if (!CryptAcquireContextW(&hProv, L"RememberedContainer", MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_MACHINE_KEYSET))
572*5e7646d2SAndroid Build Coastguard Worker {
573*5e7646d2SAndroid Build Coastguard Worker if (GetLastError() == NTE_EXISTS)
574*5e7646d2SAndroid Build Coastguard Worker {
575*5e7646d2SAndroid Build Coastguard Worker if (!CryptAcquireContextW(&hProv, L"RememberedContainer", MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET))
576*5e7646d2SAndroid Build Coastguard Worker {
577*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1httpSaveCredentials: CryptAcquireContext failed: %s", http_sspi_strerror(error, sizeof(error), GetLastError())));
578*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
579*5e7646d2SAndroid Build Coastguard Worker }
580*5e7646d2SAndroid Build Coastguard Worker }
581*5e7646d2SAndroid Build Coastguard Worker }
582*5e7646d2SAndroid Build Coastguard Worker
583*5e7646d2SAndroid Build Coastguard Worker store = CertOpenStore(CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING|PKCS_7_ASN_ENCODING, hProv, CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_NO_CRYPT_RELEASE_FLAG | CERT_STORE_OPEN_EXISTING_FLAG, L"MY");
584*5e7646d2SAndroid Build Coastguard Worker
585*5e7646d2SAndroid Build Coastguard Worker if (!store)
586*5e7646d2SAndroid Build Coastguard Worker {
587*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1httpSaveCredentials: CertOpenSystemStore failed: %s", http_sspi_strerror(error, sizeof(error), GetLastError())));
588*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
589*5e7646d2SAndroid Build Coastguard Worker }
590*5e7646d2SAndroid Build Coastguard Worker
591*5e7646d2SAndroid Build Coastguard Worker dwSize = 0;
592*5e7646d2SAndroid Build Coastguard Worker
593*5e7646d2SAndroid Build Coastguard Worker if (!CertStrToNameA(X509_ASN_ENCODING, common_name, CERT_OID_NAME_STR, NULL, NULL, &dwSize, NULL))
594*5e7646d2SAndroid Build Coastguard Worker {
595*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1httpSaveCredentials: CertStrToName failed: %s", http_sspi_strerror(error, sizeof(error), GetLastError())));
596*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
597*5e7646d2SAndroid Build Coastguard Worker }
598*5e7646d2SAndroid Build Coastguard Worker
599*5e7646d2SAndroid Build Coastguard Worker p = (PBYTE)malloc(dwSize);
600*5e7646d2SAndroid Build Coastguard Worker
601*5e7646d2SAndroid Build Coastguard Worker if (!p)
602*5e7646d2SAndroid Build Coastguard Worker {
603*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1httpSaveCredentials: malloc failed for %d bytes.", dwSize));
604*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
605*5e7646d2SAndroid Build Coastguard Worker }
606*5e7646d2SAndroid Build Coastguard Worker
607*5e7646d2SAndroid Build Coastguard Worker if (!CertStrToNameA(X509_ASN_ENCODING, common_name, CERT_OID_NAME_STR, NULL, p, &dwSize, NULL))
608*5e7646d2SAndroid Build Coastguard Worker {
609*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1httpSaveCredentials: CertStrToName failed: %s", http_sspi_strerror(error, sizeof(error), GetLastError())));
610*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
611*5e7646d2SAndroid Build Coastguard Worker }
612*5e7646d2SAndroid Build Coastguard Worker
613*5e7646d2SAndroid Build Coastguard Worker /*
614*5e7646d2SAndroid Build Coastguard Worker * Add the created context to the named store, and associate it with the named
615*5e7646d2SAndroid Build Coastguard Worker * container...
616*5e7646d2SAndroid Build Coastguard Worker */
617*5e7646d2SAndroid Build Coastguard Worker
618*5e7646d2SAndroid Build Coastguard Worker if (!CertAddCertificateContextToStore(store, createdContext, CERT_STORE_ADD_REPLACE_EXISTING, &storedContext))
619*5e7646d2SAndroid Build Coastguard Worker {
620*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1httpSaveCredentials: CertAddCertificateContextToStore failed: %s", http_sspi_strerror(error, sizeof(error), GetLastError())));
621*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
622*5e7646d2SAndroid Build Coastguard Worker }
623*5e7646d2SAndroid Build Coastguard Worker
624*5e7646d2SAndroid Build Coastguard Worker ZeroMemory(&ckp, sizeof(ckp));
625*5e7646d2SAndroid Build Coastguard Worker ckp.pwszContainerName = L"RememberedContainer";
626*5e7646d2SAndroid Build Coastguard Worker ckp.pwszProvName = MS_DEF_PROV_W;
627*5e7646d2SAndroid Build Coastguard Worker ckp.dwProvType = PROV_RSA_FULL;
628*5e7646d2SAndroid Build Coastguard Worker ckp.dwFlags = CRYPT_MACHINE_KEYSET;
629*5e7646d2SAndroid Build Coastguard Worker ckp.dwKeySpec = AT_KEYEXCHANGE;
630*5e7646d2SAndroid Build Coastguard Worker
631*5e7646d2SAndroid Build Coastguard Worker if (!CertSetCertificateContextProperty(storedContext, CERT_KEY_PROV_INFO_PROP_ID, 0, &ckp))
632*5e7646d2SAndroid Build Coastguard Worker {
633*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1httpSaveCredentials: CertSetCertificateContextProperty failed: %s", http_sspi_strerror(error, sizeof(error), GetLastError())));
634*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
635*5e7646d2SAndroid Build Coastguard Worker }
636*5e7646d2SAndroid Build Coastguard Worker
637*5e7646d2SAndroid Build Coastguard Worker ret = 0;
638*5e7646d2SAndroid Build Coastguard Worker
639*5e7646d2SAndroid Build Coastguard Worker cleanup:
640*5e7646d2SAndroid Build Coastguard Worker
641*5e7646d2SAndroid Build Coastguard Worker /*
642*5e7646d2SAndroid Build Coastguard Worker * Cleanup
643*5e7646d2SAndroid Build Coastguard Worker */
644*5e7646d2SAndroid Build Coastguard Worker
645*5e7646d2SAndroid Build Coastguard Worker if (createdContext)
646*5e7646d2SAndroid Build Coastguard Worker CertFreeCertificateContext(createdContext);
647*5e7646d2SAndroid Build Coastguard Worker
648*5e7646d2SAndroid Build Coastguard Worker if (storedContext)
649*5e7646d2SAndroid Build Coastguard Worker CertFreeCertificateContext(storedContext);
650*5e7646d2SAndroid Build Coastguard Worker
651*5e7646d2SAndroid Build Coastguard Worker if (p)
652*5e7646d2SAndroid Build Coastguard Worker free(p);
653*5e7646d2SAndroid Build Coastguard Worker
654*5e7646d2SAndroid Build Coastguard Worker if (store)
655*5e7646d2SAndroid Build Coastguard Worker CertCloseStore(store, 0);
656*5e7646d2SAndroid Build Coastguard Worker
657*5e7646d2SAndroid Build Coastguard Worker if (hProv)
658*5e7646d2SAndroid Build Coastguard Worker CryptReleaseContext(hProv, 0);
659*5e7646d2SAndroid Build Coastguard Worker
660*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1httpSaveCredentials: Returning %d.", ret));
661*5e7646d2SAndroid Build Coastguard Worker return (ret);
662*5e7646d2SAndroid Build Coastguard Worker }
663*5e7646d2SAndroid Build Coastguard Worker
664*5e7646d2SAndroid Build Coastguard Worker
665*5e7646d2SAndroid Build Coastguard Worker /*
666*5e7646d2SAndroid Build Coastguard Worker * '_httpTLSInitialize()' - Initialize the TLS stack.
667*5e7646d2SAndroid Build Coastguard Worker */
668*5e7646d2SAndroid Build Coastguard Worker
669*5e7646d2SAndroid Build Coastguard Worker void
_httpTLSInitialize(void)670*5e7646d2SAndroid Build Coastguard Worker _httpTLSInitialize(void)
671*5e7646d2SAndroid Build Coastguard Worker {
672*5e7646d2SAndroid Build Coastguard Worker /*
673*5e7646d2SAndroid Build Coastguard Worker * Nothing to do...
674*5e7646d2SAndroid Build Coastguard Worker */
675*5e7646d2SAndroid Build Coastguard Worker }
676*5e7646d2SAndroid Build Coastguard Worker
677*5e7646d2SAndroid Build Coastguard Worker
678*5e7646d2SAndroid Build Coastguard Worker /*
679*5e7646d2SAndroid Build Coastguard Worker * '_httpTLSPending()' - Return the number of pending TLS-encrypted bytes.
680*5e7646d2SAndroid Build Coastguard Worker */
681*5e7646d2SAndroid Build Coastguard Worker
682*5e7646d2SAndroid Build Coastguard Worker size_t /* O - Bytes available */
_httpTLSPending(http_t * http)683*5e7646d2SAndroid Build Coastguard Worker _httpTLSPending(http_t *http) /* I - HTTP connection */
684*5e7646d2SAndroid Build Coastguard Worker {
685*5e7646d2SAndroid Build Coastguard Worker if (http->tls)
686*5e7646d2SAndroid Build Coastguard Worker return (http->tls->readBufferUsed);
687*5e7646d2SAndroid Build Coastguard Worker else
688*5e7646d2SAndroid Build Coastguard Worker return (0);
689*5e7646d2SAndroid Build Coastguard Worker }
690*5e7646d2SAndroid Build Coastguard Worker
691*5e7646d2SAndroid Build Coastguard Worker
692*5e7646d2SAndroid Build Coastguard Worker /*
693*5e7646d2SAndroid Build Coastguard Worker * '_httpTLSRead()' - Read from a SSL/TLS connection.
694*5e7646d2SAndroid Build Coastguard Worker */
695*5e7646d2SAndroid Build Coastguard Worker
696*5e7646d2SAndroid Build Coastguard Worker int /* O - Bytes read */
_httpTLSRead(http_t * http,char * buf,int len)697*5e7646d2SAndroid Build Coastguard Worker _httpTLSRead(http_t *http, /* I - HTTP connection */
698*5e7646d2SAndroid Build Coastguard Worker char *buf, /* I - Buffer to store data */
699*5e7646d2SAndroid Build Coastguard Worker int len) /* I - Length of buffer */
700*5e7646d2SAndroid Build Coastguard Worker {
701*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
702*5e7646d2SAndroid Build Coastguard Worker _http_sspi_t *sspi = http->tls; /* SSPI data */
703*5e7646d2SAndroid Build Coastguard Worker SecBufferDesc message; /* Array of SecBuffer struct */
704*5e7646d2SAndroid Build Coastguard Worker SecBuffer buffers[4] = { 0 }; /* Security package buffer */
705*5e7646d2SAndroid Build Coastguard Worker int num = 0; /* Return value */
706*5e7646d2SAndroid Build Coastguard Worker PSecBuffer pDataBuffer; /* Data buffer */
707*5e7646d2SAndroid Build Coastguard Worker PSecBuffer pExtraBuffer; /* Excess data buffer */
708*5e7646d2SAndroid Build Coastguard Worker SECURITY_STATUS scRet; /* SSPI status */
709*5e7646d2SAndroid Build Coastguard Worker
710*5e7646d2SAndroid Build Coastguard Worker
711*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4_httpTLSRead(http=%p, buf=%p, len=%d)", http, buf, len));
712*5e7646d2SAndroid Build Coastguard Worker
713*5e7646d2SAndroid Build Coastguard Worker /*
714*5e7646d2SAndroid Build Coastguard Worker * If there are bytes that have already been decrypted and have not yet been
715*5e7646d2SAndroid Build Coastguard Worker * read, return those...
716*5e7646d2SAndroid Build Coastguard Worker */
717*5e7646d2SAndroid Build Coastguard Worker
718*5e7646d2SAndroid Build Coastguard Worker if (sspi->readBufferUsed > 0)
719*5e7646d2SAndroid Build Coastguard Worker {
720*5e7646d2SAndroid Build Coastguard Worker int bytesToCopy = min(sspi->readBufferUsed, len);
721*5e7646d2SAndroid Build Coastguard Worker /* Number of bytes to copy */
722*5e7646d2SAndroid Build Coastguard Worker
723*5e7646d2SAndroid Build Coastguard Worker memcpy(buf, sspi->readBuffer, bytesToCopy);
724*5e7646d2SAndroid Build Coastguard Worker sspi->readBufferUsed -= bytesToCopy;
725*5e7646d2SAndroid Build Coastguard Worker
726*5e7646d2SAndroid Build Coastguard Worker if (sspi->readBufferUsed > 0)
727*5e7646d2SAndroid Build Coastguard Worker memmove(sspi->readBuffer, sspi->readBuffer + bytesToCopy, sspi->readBufferUsed);
728*5e7646d2SAndroid Build Coastguard Worker
729*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5_httpTLSRead: Returning %d bytes previously decrypted.", bytesToCopy));
730*5e7646d2SAndroid Build Coastguard Worker
731*5e7646d2SAndroid Build Coastguard Worker return (bytesToCopy);
732*5e7646d2SAndroid Build Coastguard Worker }
733*5e7646d2SAndroid Build Coastguard Worker
734*5e7646d2SAndroid Build Coastguard Worker /*
735*5e7646d2SAndroid Build Coastguard Worker * Initialize security buffer structs
736*5e7646d2SAndroid Build Coastguard Worker */
737*5e7646d2SAndroid Build Coastguard Worker
738*5e7646d2SAndroid Build Coastguard Worker message.ulVersion = SECBUFFER_VERSION;
739*5e7646d2SAndroid Build Coastguard Worker message.cBuffers = 4;
740*5e7646d2SAndroid Build Coastguard Worker message.pBuffers = buffers;
741*5e7646d2SAndroid Build Coastguard Worker
742*5e7646d2SAndroid Build Coastguard Worker do
743*5e7646d2SAndroid Build Coastguard Worker {
744*5e7646d2SAndroid Build Coastguard Worker /*
745*5e7646d2SAndroid Build Coastguard Worker * If there is not enough space in the buffer, then increase its size...
746*5e7646d2SAndroid Build Coastguard Worker */
747*5e7646d2SAndroid Build Coastguard Worker
748*5e7646d2SAndroid Build Coastguard Worker if (sspi->decryptBufferLength <= sspi->decryptBufferUsed)
749*5e7646d2SAndroid Build Coastguard Worker {
750*5e7646d2SAndroid Build Coastguard Worker BYTE *temp; /* New buffer */
751*5e7646d2SAndroid Build Coastguard Worker
752*5e7646d2SAndroid Build Coastguard Worker if (sspi->decryptBufferLength >= 262144)
753*5e7646d2SAndroid Build Coastguard Worker {
754*5e7646d2SAndroid Build Coastguard Worker WSASetLastError(E_OUTOFMEMORY);
755*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("_httpTLSRead: Decryption buffer too large (>256k)");
756*5e7646d2SAndroid Build Coastguard Worker return (-1);
757*5e7646d2SAndroid Build Coastguard Worker }
758*5e7646d2SAndroid Build Coastguard Worker
759*5e7646d2SAndroid Build Coastguard Worker if ((temp = realloc(sspi->decryptBuffer, sspi->decryptBufferLength + 4096)) == NULL)
760*5e7646d2SAndroid Build Coastguard Worker {
761*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("_httpTLSRead: Unable to allocate %d byte decryption buffer.", sspi->decryptBufferLength + 4096));
762*5e7646d2SAndroid Build Coastguard Worker WSASetLastError(E_OUTOFMEMORY);
763*5e7646d2SAndroid Build Coastguard Worker return (-1);
764*5e7646d2SAndroid Build Coastguard Worker }
765*5e7646d2SAndroid Build Coastguard Worker
766*5e7646d2SAndroid Build Coastguard Worker sspi->decryptBufferLength += 4096;
767*5e7646d2SAndroid Build Coastguard Worker sspi->decryptBuffer = temp;
768*5e7646d2SAndroid Build Coastguard Worker
769*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("_httpTLSRead: Resized decryption buffer to %d bytes.", sspi->decryptBufferLength));
770*5e7646d2SAndroid Build Coastguard Worker }
771*5e7646d2SAndroid Build Coastguard Worker
772*5e7646d2SAndroid Build Coastguard Worker buffers[0].pvBuffer = sspi->decryptBuffer;
773*5e7646d2SAndroid Build Coastguard Worker buffers[0].cbBuffer = (unsigned long)sspi->decryptBufferUsed;
774*5e7646d2SAndroid Build Coastguard Worker buffers[0].BufferType = SECBUFFER_DATA;
775*5e7646d2SAndroid Build Coastguard Worker buffers[1].BufferType = SECBUFFER_EMPTY;
776*5e7646d2SAndroid Build Coastguard Worker buffers[2].BufferType = SECBUFFER_EMPTY;
777*5e7646d2SAndroid Build Coastguard Worker buffers[3].BufferType = SECBUFFER_EMPTY;
778*5e7646d2SAndroid Build Coastguard Worker
779*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5_httpTLSRead: decryptBufferUsed=%d", sspi->decryptBufferUsed));
780*5e7646d2SAndroid Build Coastguard Worker
781*5e7646d2SAndroid Build Coastguard Worker scRet = DecryptMessage(&sspi->context, &message, 0, NULL);
782*5e7646d2SAndroid Build Coastguard Worker
783*5e7646d2SAndroid Build Coastguard Worker if (scRet == SEC_E_INCOMPLETE_MESSAGE)
784*5e7646d2SAndroid Build Coastguard Worker {
785*5e7646d2SAndroid Build Coastguard Worker num = recv(http->fd, sspi->decryptBuffer + sspi->decryptBufferUsed, (int)(sspi->decryptBufferLength - sspi->decryptBufferUsed), 0);
786*5e7646d2SAndroid Build Coastguard Worker if (num < 0)
787*5e7646d2SAndroid Build Coastguard Worker {
788*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5_httpTLSRead: recv failed: %d", WSAGetLastError()));
789*5e7646d2SAndroid Build Coastguard Worker return (-1);
790*5e7646d2SAndroid Build Coastguard Worker }
791*5e7646d2SAndroid Build Coastguard Worker else if (num == 0)
792*5e7646d2SAndroid Build Coastguard Worker {
793*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5_httpTLSRead: Server disconnected.");
794*5e7646d2SAndroid Build Coastguard Worker return (0);
795*5e7646d2SAndroid Build Coastguard Worker }
796*5e7646d2SAndroid Build Coastguard Worker
797*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5_httpTLSRead: Read %d bytes into decryption buffer.", num));
798*5e7646d2SAndroid Build Coastguard Worker
799*5e7646d2SAndroid Build Coastguard Worker sspi->decryptBufferUsed += num;
800*5e7646d2SAndroid Build Coastguard Worker }
801*5e7646d2SAndroid Build Coastguard Worker }
802*5e7646d2SAndroid Build Coastguard Worker while (scRet == SEC_E_INCOMPLETE_MESSAGE);
803*5e7646d2SAndroid Build Coastguard Worker
804*5e7646d2SAndroid Build Coastguard Worker if (scRet == SEC_I_CONTEXT_EXPIRED)
805*5e7646d2SAndroid Build Coastguard Worker {
806*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5_httpTLSRead: Context expired.");
807*5e7646d2SAndroid Build Coastguard Worker WSASetLastError(WSAECONNRESET);
808*5e7646d2SAndroid Build Coastguard Worker return (-1);
809*5e7646d2SAndroid Build Coastguard Worker }
810*5e7646d2SAndroid Build Coastguard Worker else if (scRet != SEC_E_OK)
811*5e7646d2SAndroid Build Coastguard Worker {
812*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5_httpTLSRead: DecryptMessage failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), scRet)));
813*5e7646d2SAndroid Build Coastguard Worker WSASetLastError(WSASYSCALLFAILURE);
814*5e7646d2SAndroid Build Coastguard Worker return (-1);
815*5e7646d2SAndroid Build Coastguard Worker }
816*5e7646d2SAndroid Build Coastguard Worker
817*5e7646d2SAndroid Build Coastguard Worker /*
818*5e7646d2SAndroid Build Coastguard Worker * The decryption worked. Now, locate data buffer.
819*5e7646d2SAndroid Build Coastguard Worker */
820*5e7646d2SAndroid Build Coastguard Worker
821*5e7646d2SAndroid Build Coastguard Worker pDataBuffer = NULL;
822*5e7646d2SAndroid Build Coastguard Worker pExtraBuffer = NULL;
823*5e7646d2SAndroid Build Coastguard Worker
824*5e7646d2SAndroid Build Coastguard Worker for (i = 1; i < 4; i++)
825*5e7646d2SAndroid Build Coastguard Worker {
826*5e7646d2SAndroid Build Coastguard Worker if (buffers[i].BufferType == SECBUFFER_DATA)
827*5e7646d2SAndroid Build Coastguard Worker pDataBuffer = &buffers[i];
828*5e7646d2SAndroid Build Coastguard Worker else if (!pExtraBuffer && (buffers[i].BufferType == SECBUFFER_EXTRA))
829*5e7646d2SAndroid Build Coastguard Worker pExtraBuffer = &buffers[i];
830*5e7646d2SAndroid Build Coastguard Worker }
831*5e7646d2SAndroid Build Coastguard Worker
832*5e7646d2SAndroid Build Coastguard Worker /*
833*5e7646d2SAndroid Build Coastguard Worker * If a data buffer is found, then copy the decrypted bytes to the passed-in
834*5e7646d2SAndroid Build Coastguard Worker * buffer...
835*5e7646d2SAndroid Build Coastguard Worker */
836*5e7646d2SAndroid Build Coastguard Worker
837*5e7646d2SAndroid Build Coastguard Worker if (pDataBuffer)
838*5e7646d2SAndroid Build Coastguard Worker {
839*5e7646d2SAndroid Build Coastguard Worker int bytesToCopy = min((int)pDataBuffer->cbBuffer, len);
840*5e7646d2SAndroid Build Coastguard Worker /* Number of bytes to copy into buf */
841*5e7646d2SAndroid Build Coastguard Worker int bytesToSave = pDataBuffer->cbBuffer - bytesToCopy;
842*5e7646d2SAndroid Build Coastguard Worker /* Number of bytes to save in our read buffer */
843*5e7646d2SAndroid Build Coastguard Worker
844*5e7646d2SAndroid Build Coastguard Worker if (bytesToCopy)
845*5e7646d2SAndroid Build Coastguard Worker memcpy(buf, pDataBuffer->pvBuffer, bytesToCopy);
846*5e7646d2SAndroid Build Coastguard Worker
847*5e7646d2SAndroid Build Coastguard Worker /*
848*5e7646d2SAndroid Build Coastguard Worker * If there are more decrypted bytes than can be copied to the passed in
849*5e7646d2SAndroid Build Coastguard Worker * buffer, then save them...
850*5e7646d2SAndroid Build Coastguard Worker */
851*5e7646d2SAndroid Build Coastguard Worker
852*5e7646d2SAndroid Build Coastguard Worker if (bytesToSave)
853*5e7646d2SAndroid Build Coastguard Worker {
854*5e7646d2SAndroid Build Coastguard Worker if ((sspi->readBufferLength - sspi->readBufferUsed) < bytesToSave)
855*5e7646d2SAndroid Build Coastguard Worker {
856*5e7646d2SAndroid Build Coastguard Worker BYTE *temp; /* New buffer pointer */
857*5e7646d2SAndroid Build Coastguard Worker
858*5e7646d2SAndroid Build Coastguard Worker if ((temp = realloc(sspi->readBuffer, sspi->readBufferUsed + bytesToSave)) == NULL)
859*5e7646d2SAndroid Build Coastguard Worker {
860*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("_httpTLSRead: Unable to allocate %d bytes.", sspi->readBufferUsed + bytesToSave));
861*5e7646d2SAndroid Build Coastguard Worker WSASetLastError(E_OUTOFMEMORY);
862*5e7646d2SAndroid Build Coastguard Worker return (-1);
863*5e7646d2SAndroid Build Coastguard Worker }
864*5e7646d2SAndroid Build Coastguard Worker
865*5e7646d2SAndroid Build Coastguard Worker sspi->readBufferLength = sspi->readBufferUsed + bytesToSave;
866*5e7646d2SAndroid Build Coastguard Worker sspi->readBuffer = temp;
867*5e7646d2SAndroid Build Coastguard Worker }
868*5e7646d2SAndroid Build Coastguard Worker
869*5e7646d2SAndroid Build Coastguard Worker memcpy(((BYTE *)sspi->readBuffer) + sspi->readBufferUsed, ((BYTE *)pDataBuffer->pvBuffer) + bytesToCopy, bytesToSave);
870*5e7646d2SAndroid Build Coastguard Worker
871*5e7646d2SAndroid Build Coastguard Worker sspi->readBufferUsed += bytesToSave;
872*5e7646d2SAndroid Build Coastguard Worker }
873*5e7646d2SAndroid Build Coastguard Worker
874*5e7646d2SAndroid Build Coastguard Worker num = bytesToCopy;
875*5e7646d2SAndroid Build Coastguard Worker }
876*5e7646d2SAndroid Build Coastguard Worker else
877*5e7646d2SAndroid Build Coastguard Worker {
878*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("_httpTLSRead: Unable to find data buffer.");
879*5e7646d2SAndroid Build Coastguard Worker WSASetLastError(WSASYSCALLFAILURE);
880*5e7646d2SAndroid Build Coastguard Worker return (-1);
881*5e7646d2SAndroid Build Coastguard Worker }
882*5e7646d2SAndroid Build Coastguard Worker
883*5e7646d2SAndroid Build Coastguard Worker /*
884*5e7646d2SAndroid Build Coastguard Worker * If the decryption process left extra bytes, then save those back in
885*5e7646d2SAndroid Build Coastguard Worker * decryptBuffer. They will be processed the next time through the loop.
886*5e7646d2SAndroid Build Coastguard Worker */
887*5e7646d2SAndroid Build Coastguard Worker
888*5e7646d2SAndroid Build Coastguard Worker if (pExtraBuffer)
889*5e7646d2SAndroid Build Coastguard Worker {
890*5e7646d2SAndroid Build Coastguard Worker memmove(sspi->decryptBuffer, pExtraBuffer->pvBuffer, pExtraBuffer->cbBuffer);
891*5e7646d2SAndroid Build Coastguard Worker sspi->decryptBufferUsed = pExtraBuffer->cbBuffer;
892*5e7646d2SAndroid Build Coastguard Worker }
893*5e7646d2SAndroid Build Coastguard Worker else
894*5e7646d2SAndroid Build Coastguard Worker {
895*5e7646d2SAndroid Build Coastguard Worker sspi->decryptBufferUsed = 0;
896*5e7646d2SAndroid Build Coastguard Worker }
897*5e7646d2SAndroid Build Coastguard Worker
898*5e7646d2SAndroid Build Coastguard Worker return (num);
899*5e7646d2SAndroid Build Coastguard Worker }
900*5e7646d2SAndroid Build Coastguard Worker
901*5e7646d2SAndroid Build Coastguard Worker
902*5e7646d2SAndroid Build Coastguard Worker /*
903*5e7646d2SAndroid Build Coastguard Worker * '_httpTLSSetOptions()' - Set TLS protocol and cipher suite options.
904*5e7646d2SAndroid Build Coastguard Worker */
905*5e7646d2SAndroid Build Coastguard Worker
906*5e7646d2SAndroid Build Coastguard Worker void
_httpTLSSetOptions(int options,int min_version,int max_version)907*5e7646d2SAndroid Build Coastguard Worker _httpTLSSetOptions(int options, /* I - Options */
908*5e7646d2SAndroid Build Coastguard Worker int min_version, /* I - Minimum TLS version */
909*5e7646d2SAndroid Build Coastguard Worker int max_version) /* I - Maximum TLS version */
910*5e7646d2SAndroid Build Coastguard Worker {
911*5e7646d2SAndroid Build Coastguard Worker if (!(options & _HTTP_TLS_SET_DEFAULT) || tls_options < 0)
912*5e7646d2SAndroid Build Coastguard Worker {
913*5e7646d2SAndroid Build Coastguard Worker tls_options = options;
914*5e7646d2SAndroid Build Coastguard Worker tls_min_version = min_version;
915*5e7646d2SAndroid Build Coastguard Worker tls_max_version = max_version;
916*5e7646d2SAndroid Build Coastguard Worker }
917*5e7646d2SAndroid Build Coastguard Worker }
918*5e7646d2SAndroid Build Coastguard Worker
919*5e7646d2SAndroid Build Coastguard Worker
920*5e7646d2SAndroid Build Coastguard Worker /*
921*5e7646d2SAndroid Build Coastguard Worker * '_httpTLSStart()' - Set up SSL/TLS support on a connection.
922*5e7646d2SAndroid Build Coastguard Worker */
923*5e7646d2SAndroid Build Coastguard Worker
924*5e7646d2SAndroid Build Coastguard Worker int /* O - 0 on success, -1 on failure */
_httpTLSStart(http_t * http)925*5e7646d2SAndroid Build Coastguard Worker _httpTLSStart(http_t *http) /* I - HTTP connection */
926*5e7646d2SAndroid Build Coastguard Worker {
927*5e7646d2SAndroid Build Coastguard Worker char hostname[256], /* Hostname */
928*5e7646d2SAndroid Build Coastguard Worker *hostptr; /* Pointer into hostname */
929*5e7646d2SAndroid Build Coastguard Worker
930*5e7646d2SAndroid Build Coastguard Worker
931*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("3_httpTLSStart(http=%p)", http));
932*5e7646d2SAndroid Build Coastguard Worker
933*5e7646d2SAndroid Build Coastguard Worker if (tls_options < 0)
934*5e7646d2SAndroid Build Coastguard Worker {
935*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("4_httpTLSStart: Setting defaults.");
936*5e7646d2SAndroid Build Coastguard Worker _cupsSetDefaults();
937*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4_httpTLSStart: tls_options=%x", tls_options));
938*5e7646d2SAndroid Build Coastguard Worker }
939*5e7646d2SAndroid Build Coastguard Worker
940*5e7646d2SAndroid Build Coastguard Worker if ((http->tls = http_sspi_alloc()) == NULL)
941*5e7646d2SAndroid Build Coastguard Worker return (-1);
942*5e7646d2SAndroid Build Coastguard Worker
943*5e7646d2SAndroid Build Coastguard Worker if (http->mode == _HTTP_MODE_CLIENT)
944*5e7646d2SAndroid Build Coastguard Worker {
945*5e7646d2SAndroid Build Coastguard Worker /*
946*5e7646d2SAndroid Build Coastguard Worker * Client: determine hostname...
947*5e7646d2SAndroid Build Coastguard Worker */
948*5e7646d2SAndroid Build Coastguard Worker
949*5e7646d2SAndroid Build Coastguard Worker if (httpAddrLocalhost(http->hostaddr))
950*5e7646d2SAndroid Build Coastguard Worker {
951*5e7646d2SAndroid Build Coastguard Worker strlcpy(hostname, "localhost", sizeof(hostname));
952*5e7646d2SAndroid Build Coastguard Worker }
953*5e7646d2SAndroid Build Coastguard Worker else
954*5e7646d2SAndroid Build Coastguard Worker {
955*5e7646d2SAndroid Build Coastguard Worker /*
956*5e7646d2SAndroid Build Coastguard Worker * Otherwise make sure the hostname we have does not end in a trailing dot.
957*5e7646d2SAndroid Build Coastguard Worker */
958*5e7646d2SAndroid Build Coastguard Worker
959*5e7646d2SAndroid Build Coastguard Worker strlcpy(hostname, http->hostname, sizeof(hostname));
960*5e7646d2SAndroid Build Coastguard Worker if ((hostptr = hostname + strlen(hostname) - 1) >= hostname &&
961*5e7646d2SAndroid Build Coastguard Worker *hostptr == '.')
962*5e7646d2SAndroid Build Coastguard Worker *hostptr = '\0';
963*5e7646d2SAndroid Build Coastguard Worker }
964*5e7646d2SAndroid Build Coastguard Worker
965*5e7646d2SAndroid Build Coastguard Worker return (http_sspi_client(http, hostname));
966*5e7646d2SAndroid Build Coastguard Worker }
967*5e7646d2SAndroid Build Coastguard Worker else
968*5e7646d2SAndroid Build Coastguard Worker {
969*5e7646d2SAndroid Build Coastguard Worker /*
970*5e7646d2SAndroid Build Coastguard Worker * Server: determine hostname to use...
971*5e7646d2SAndroid Build Coastguard Worker */
972*5e7646d2SAndroid Build Coastguard Worker
973*5e7646d2SAndroid Build Coastguard Worker if (http->fields[HTTP_FIELD_HOST])
974*5e7646d2SAndroid Build Coastguard Worker {
975*5e7646d2SAndroid Build Coastguard Worker /*
976*5e7646d2SAndroid Build Coastguard Worker * Use hostname for TLS upgrade...
977*5e7646d2SAndroid Build Coastguard Worker */
978*5e7646d2SAndroid Build Coastguard Worker
979*5e7646d2SAndroid Build Coastguard Worker strlcpy(hostname, http->fields[HTTP_FIELD_HOST], sizeof(hostname));
980*5e7646d2SAndroid Build Coastguard Worker }
981*5e7646d2SAndroid Build Coastguard Worker else
982*5e7646d2SAndroid Build Coastguard Worker {
983*5e7646d2SAndroid Build Coastguard Worker /*
984*5e7646d2SAndroid Build Coastguard Worker * Resolve hostname from connection address...
985*5e7646d2SAndroid Build Coastguard Worker */
986*5e7646d2SAndroid Build Coastguard Worker
987*5e7646d2SAndroid Build Coastguard Worker http_addr_t addr; /* Connection address */
988*5e7646d2SAndroid Build Coastguard Worker socklen_t addrlen; /* Length of address */
989*5e7646d2SAndroid Build Coastguard Worker
990*5e7646d2SAndroid Build Coastguard Worker addrlen = sizeof(addr);
991*5e7646d2SAndroid Build Coastguard Worker if (getsockname(http->fd, (struct sockaddr *)&addr, &addrlen))
992*5e7646d2SAndroid Build Coastguard Worker {
993*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4_httpTLSStart: Unable to get socket address: %s", strerror(errno)));
994*5e7646d2SAndroid Build Coastguard Worker hostname[0] = '\0';
995*5e7646d2SAndroid Build Coastguard Worker }
996*5e7646d2SAndroid Build Coastguard Worker else if (httpAddrLocalhost(&addr))
997*5e7646d2SAndroid Build Coastguard Worker hostname[0] = '\0';
998*5e7646d2SAndroid Build Coastguard Worker else
999*5e7646d2SAndroid Build Coastguard Worker {
1000*5e7646d2SAndroid Build Coastguard Worker httpAddrLookup(&addr, hostname, sizeof(hostname));
1001*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4_httpTLSStart: Resolved socket address to \"%s\".", hostname));
1002*5e7646d2SAndroid Build Coastguard Worker }
1003*5e7646d2SAndroid Build Coastguard Worker }
1004*5e7646d2SAndroid Build Coastguard Worker
1005*5e7646d2SAndroid Build Coastguard Worker return (http_sspi_server(http, hostname));
1006*5e7646d2SAndroid Build Coastguard Worker }
1007*5e7646d2SAndroid Build Coastguard Worker }
1008*5e7646d2SAndroid Build Coastguard Worker
1009*5e7646d2SAndroid Build Coastguard Worker
1010*5e7646d2SAndroid Build Coastguard Worker /*
1011*5e7646d2SAndroid Build Coastguard Worker * '_httpTLSStop()' - Shut down SSL/TLS on a connection.
1012*5e7646d2SAndroid Build Coastguard Worker */
1013*5e7646d2SAndroid Build Coastguard Worker
1014*5e7646d2SAndroid Build Coastguard Worker void
_httpTLSStop(http_t * http)1015*5e7646d2SAndroid Build Coastguard Worker _httpTLSStop(http_t *http) /* I - HTTP connection */
1016*5e7646d2SAndroid Build Coastguard Worker {
1017*5e7646d2SAndroid Build Coastguard Worker _http_sspi_t *sspi = http->tls; /* SSPI data */
1018*5e7646d2SAndroid Build Coastguard Worker
1019*5e7646d2SAndroid Build Coastguard Worker
1020*5e7646d2SAndroid Build Coastguard Worker if (sspi->contextInitialized && http->fd >= 0)
1021*5e7646d2SAndroid Build Coastguard Worker {
1022*5e7646d2SAndroid Build Coastguard Worker SecBufferDesc message; /* Array of SecBuffer struct */
1023*5e7646d2SAndroid Build Coastguard Worker SecBuffer buffers[1] = { 0 };
1024*5e7646d2SAndroid Build Coastguard Worker /* Security package buffer */
1025*5e7646d2SAndroid Build Coastguard Worker DWORD dwType; /* Type */
1026*5e7646d2SAndroid Build Coastguard Worker DWORD status; /* Status */
1027*5e7646d2SAndroid Build Coastguard Worker
1028*5e7646d2SAndroid Build Coastguard Worker /*
1029*5e7646d2SAndroid Build Coastguard Worker * Notify schannel that we are about to close the connection.
1030*5e7646d2SAndroid Build Coastguard Worker */
1031*5e7646d2SAndroid Build Coastguard Worker
1032*5e7646d2SAndroid Build Coastguard Worker dwType = SCHANNEL_SHUTDOWN;
1033*5e7646d2SAndroid Build Coastguard Worker
1034*5e7646d2SAndroid Build Coastguard Worker buffers[0].pvBuffer = &dwType;
1035*5e7646d2SAndroid Build Coastguard Worker buffers[0].BufferType = SECBUFFER_TOKEN;
1036*5e7646d2SAndroid Build Coastguard Worker buffers[0].cbBuffer = sizeof(dwType);
1037*5e7646d2SAndroid Build Coastguard Worker
1038*5e7646d2SAndroid Build Coastguard Worker message.cBuffers = 1;
1039*5e7646d2SAndroid Build Coastguard Worker message.pBuffers = buffers;
1040*5e7646d2SAndroid Build Coastguard Worker message.ulVersion = SECBUFFER_VERSION;
1041*5e7646d2SAndroid Build Coastguard Worker
1042*5e7646d2SAndroid Build Coastguard Worker status = ApplyControlToken(&sspi->context, &message);
1043*5e7646d2SAndroid Build Coastguard Worker
1044*5e7646d2SAndroid Build Coastguard Worker if (SUCCEEDED(status))
1045*5e7646d2SAndroid Build Coastguard Worker {
1046*5e7646d2SAndroid Build Coastguard Worker PBYTE pbMessage; /* Message buffer */
1047*5e7646d2SAndroid Build Coastguard Worker DWORD cbMessage; /* Message buffer count */
1048*5e7646d2SAndroid Build Coastguard Worker DWORD cbData; /* Data count */
1049*5e7646d2SAndroid Build Coastguard Worker DWORD dwSSPIFlags; /* SSL attributes we requested */
1050*5e7646d2SAndroid Build Coastguard Worker DWORD dwSSPIOutFlags; /* SSL attributes we received */
1051*5e7646d2SAndroid Build Coastguard Worker TimeStamp tsExpiry; /* Time stamp */
1052*5e7646d2SAndroid Build Coastguard Worker
1053*5e7646d2SAndroid Build Coastguard Worker dwSSPIFlags = ASC_REQ_SEQUENCE_DETECT |
1054*5e7646d2SAndroid Build Coastguard Worker ASC_REQ_REPLAY_DETECT |
1055*5e7646d2SAndroid Build Coastguard Worker ASC_REQ_CONFIDENTIALITY |
1056*5e7646d2SAndroid Build Coastguard Worker ASC_REQ_EXTENDED_ERROR |
1057*5e7646d2SAndroid Build Coastguard Worker ASC_REQ_ALLOCATE_MEMORY |
1058*5e7646d2SAndroid Build Coastguard Worker ASC_REQ_STREAM;
1059*5e7646d2SAndroid Build Coastguard Worker
1060*5e7646d2SAndroid Build Coastguard Worker buffers[0].pvBuffer = NULL;
1061*5e7646d2SAndroid Build Coastguard Worker buffers[0].BufferType = SECBUFFER_TOKEN;
1062*5e7646d2SAndroid Build Coastguard Worker buffers[0].cbBuffer = 0;
1063*5e7646d2SAndroid Build Coastguard Worker
1064*5e7646d2SAndroid Build Coastguard Worker message.cBuffers = 1;
1065*5e7646d2SAndroid Build Coastguard Worker message.pBuffers = buffers;
1066*5e7646d2SAndroid Build Coastguard Worker message.ulVersion = SECBUFFER_VERSION;
1067*5e7646d2SAndroid Build Coastguard Worker
1068*5e7646d2SAndroid Build Coastguard Worker status = AcceptSecurityContext(&sspi->creds, &sspi->context, NULL,
1069*5e7646d2SAndroid Build Coastguard Worker dwSSPIFlags, SECURITY_NATIVE_DREP, NULL,
1070*5e7646d2SAndroid Build Coastguard Worker &message, &dwSSPIOutFlags, &tsExpiry);
1071*5e7646d2SAndroid Build Coastguard Worker
1072*5e7646d2SAndroid Build Coastguard Worker if (SUCCEEDED(status))
1073*5e7646d2SAndroid Build Coastguard Worker {
1074*5e7646d2SAndroid Build Coastguard Worker pbMessage = buffers[0].pvBuffer;
1075*5e7646d2SAndroid Build Coastguard Worker cbMessage = buffers[0].cbBuffer;
1076*5e7646d2SAndroid Build Coastguard Worker
1077*5e7646d2SAndroid Build Coastguard Worker /*
1078*5e7646d2SAndroid Build Coastguard Worker * Send the close notify message to the client.
1079*5e7646d2SAndroid Build Coastguard Worker */
1080*5e7646d2SAndroid Build Coastguard Worker
1081*5e7646d2SAndroid Build Coastguard Worker if (pbMessage && cbMessage)
1082*5e7646d2SAndroid Build Coastguard Worker {
1083*5e7646d2SAndroid Build Coastguard Worker cbData = send(http->fd, pbMessage, cbMessage, 0);
1084*5e7646d2SAndroid Build Coastguard Worker if ((cbData == SOCKET_ERROR) || (cbData == 0))
1085*5e7646d2SAndroid Build Coastguard Worker {
1086*5e7646d2SAndroid Build Coastguard Worker status = WSAGetLastError();
1087*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("_httpTLSStop: sending close notify failed: %d", status));
1088*5e7646d2SAndroid Build Coastguard Worker }
1089*5e7646d2SAndroid Build Coastguard Worker else
1090*5e7646d2SAndroid Build Coastguard Worker {
1091*5e7646d2SAndroid Build Coastguard Worker FreeContextBuffer(pbMessage);
1092*5e7646d2SAndroid Build Coastguard Worker }
1093*5e7646d2SAndroid Build Coastguard Worker }
1094*5e7646d2SAndroid Build Coastguard Worker }
1095*5e7646d2SAndroid Build Coastguard Worker else
1096*5e7646d2SAndroid Build Coastguard Worker {
1097*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("_httpTLSStop: AcceptSecurityContext failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), status)));
1098*5e7646d2SAndroid Build Coastguard Worker }
1099*5e7646d2SAndroid Build Coastguard Worker }
1100*5e7646d2SAndroid Build Coastguard Worker else
1101*5e7646d2SAndroid Build Coastguard Worker {
1102*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("_httpTLSStop: ApplyControlToken failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), status)));
1103*5e7646d2SAndroid Build Coastguard Worker }
1104*5e7646d2SAndroid Build Coastguard Worker }
1105*5e7646d2SAndroid Build Coastguard Worker
1106*5e7646d2SAndroid Build Coastguard Worker http_sspi_free(sspi);
1107*5e7646d2SAndroid Build Coastguard Worker
1108*5e7646d2SAndroid Build Coastguard Worker http->tls = NULL;
1109*5e7646d2SAndroid Build Coastguard Worker }
1110*5e7646d2SAndroid Build Coastguard Worker
1111*5e7646d2SAndroid Build Coastguard Worker
1112*5e7646d2SAndroid Build Coastguard Worker /*
1113*5e7646d2SAndroid Build Coastguard Worker * '_httpTLSWrite()' - Write to a SSL/TLS connection.
1114*5e7646d2SAndroid Build Coastguard Worker */
1115*5e7646d2SAndroid Build Coastguard Worker
1116*5e7646d2SAndroid Build Coastguard Worker int /* O - Bytes written */
_httpTLSWrite(http_t * http,const char * buf,int len)1117*5e7646d2SAndroid Build Coastguard Worker _httpTLSWrite(http_t *http, /* I - HTTP connection */
1118*5e7646d2SAndroid Build Coastguard Worker const char *buf, /* I - Buffer holding data */
1119*5e7646d2SAndroid Build Coastguard Worker int len) /* I - Length of buffer */
1120*5e7646d2SAndroid Build Coastguard Worker {
1121*5e7646d2SAndroid Build Coastguard Worker _http_sspi_t *sspi = http->tls; /* SSPI data */
1122*5e7646d2SAndroid Build Coastguard Worker SecBufferDesc message; /* Array of SecBuffer struct */
1123*5e7646d2SAndroid Build Coastguard Worker SecBuffer buffers[4] = { 0 }; /* Security package buffer */
1124*5e7646d2SAndroid Build Coastguard Worker int bufferLen; /* Buffer length */
1125*5e7646d2SAndroid Build Coastguard Worker int bytesLeft; /* Bytes left to write */
1126*5e7646d2SAndroid Build Coastguard Worker const char *bufptr; /* Pointer into buffer */
1127*5e7646d2SAndroid Build Coastguard Worker int num = 0; /* Return value */
1128*5e7646d2SAndroid Build Coastguard Worker
1129*5e7646d2SAndroid Build Coastguard Worker
1130*5e7646d2SAndroid Build Coastguard Worker bufferLen = sspi->streamSizes.cbMaximumMessage + sspi->streamSizes.cbHeader + sspi->streamSizes.cbTrailer;
1131*5e7646d2SAndroid Build Coastguard Worker
1132*5e7646d2SAndroid Build Coastguard Worker if (bufferLen > sspi->writeBufferLength)
1133*5e7646d2SAndroid Build Coastguard Worker {
1134*5e7646d2SAndroid Build Coastguard Worker BYTE *temp; /* New buffer pointer */
1135*5e7646d2SAndroid Build Coastguard Worker
1136*5e7646d2SAndroid Build Coastguard Worker if ((temp = (BYTE *)realloc(sspi->writeBuffer, bufferLen)) == NULL)
1137*5e7646d2SAndroid Build Coastguard Worker {
1138*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("_httpTLSWrite: Unable to allocate buffer of %d bytes.", bufferLen));
1139*5e7646d2SAndroid Build Coastguard Worker WSASetLastError(E_OUTOFMEMORY);
1140*5e7646d2SAndroid Build Coastguard Worker return (-1);
1141*5e7646d2SAndroid Build Coastguard Worker }
1142*5e7646d2SAndroid Build Coastguard Worker
1143*5e7646d2SAndroid Build Coastguard Worker sspi->writeBuffer = temp;
1144*5e7646d2SAndroid Build Coastguard Worker sspi->writeBufferLength = bufferLen;
1145*5e7646d2SAndroid Build Coastguard Worker }
1146*5e7646d2SAndroid Build Coastguard Worker
1147*5e7646d2SAndroid Build Coastguard Worker bytesLeft = len;
1148*5e7646d2SAndroid Build Coastguard Worker bufptr = buf;
1149*5e7646d2SAndroid Build Coastguard Worker
1150*5e7646d2SAndroid Build Coastguard Worker while (bytesLeft)
1151*5e7646d2SAndroid Build Coastguard Worker {
1152*5e7646d2SAndroid Build Coastguard Worker int chunk = min((int)sspi->streamSizes.cbMaximumMessage, bytesLeft);
1153*5e7646d2SAndroid Build Coastguard Worker /* Size of data to write */
1154*5e7646d2SAndroid Build Coastguard Worker SECURITY_STATUS scRet; /* SSPI status */
1155*5e7646d2SAndroid Build Coastguard Worker
1156*5e7646d2SAndroid Build Coastguard Worker /*
1157*5e7646d2SAndroid Build Coastguard Worker * Copy user data into the buffer, starting just past the header...
1158*5e7646d2SAndroid Build Coastguard Worker */
1159*5e7646d2SAndroid Build Coastguard Worker
1160*5e7646d2SAndroid Build Coastguard Worker memcpy(sspi->writeBuffer + sspi->streamSizes.cbHeader, bufptr, chunk);
1161*5e7646d2SAndroid Build Coastguard Worker
1162*5e7646d2SAndroid Build Coastguard Worker /*
1163*5e7646d2SAndroid Build Coastguard Worker * Setup the SSPI buffers
1164*5e7646d2SAndroid Build Coastguard Worker */
1165*5e7646d2SAndroid Build Coastguard Worker
1166*5e7646d2SAndroid Build Coastguard Worker message.ulVersion = SECBUFFER_VERSION;
1167*5e7646d2SAndroid Build Coastguard Worker message.cBuffers = 4;
1168*5e7646d2SAndroid Build Coastguard Worker message.pBuffers = buffers;
1169*5e7646d2SAndroid Build Coastguard Worker
1170*5e7646d2SAndroid Build Coastguard Worker buffers[0].pvBuffer = sspi->writeBuffer;
1171*5e7646d2SAndroid Build Coastguard Worker buffers[0].cbBuffer = sspi->streamSizes.cbHeader;
1172*5e7646d2SAndroid Build Coastguard Worker buffers[0].BufferType = SECBUFFER_STREAM_HEADER;
1173*5e7646d2SAndroid Build Coastguard Worker buffers[1].pvBuffer = sspi->writeBuffer + sspi->streamSizes.cbHeader;
1174*5e7646d2SAndroid Build Coastguard Worker buffers[1].cbBuffer = (unsigned long) chunk;
1175*5e7646d2SAndroid Build Coastguard Worker buffers[1].BufferType = SECBUFFER_DATA;
1176*5e7646d2SAndroid Build Coastguard Worker buffers[2].pvBuffer = sspi->writeBuffer + sspi->streamSizes.cbHeader + chunk;
1177*5e7646d2SAndroid Build Coastguard Worker buffers[2].cbBuffer = sspi->streamSizes.cbTrailer;
1178*5e7646d2SAndroid Build Coastguard Worker buffers[2].BufferType = SECBUFFER_STREAM_TRAILER;
1179*5e7646d2SAndroid Build Coastguard Worker buffers[3].BufferType = SECBUFFER_EMPTY;
1180*5e7646d2SAndroid Build Coastguard Worker
1181*5e7646d2SAndroid Build Coastguard Worker /*
1182*5e7646d2SAndroid Build Coastguard Worker * Encrypt the data
1183*5e7646d2SAndroid Build Coastguard Worker */
1184*5e7646d2SAndroid Build Coastguard Worker
1185*5e7646d2SAndroid Build Coastguard Worker scRet = EncryptMessage(&sspi->context, 0, &message, 0);
1186*5e7646d2SAndroid Build Coastguard Worker
1187*5e7646d2SAndroid Build Coastguard Worker if (FAILED(scRet))
1188*5e7646d2SAndroid Build Coastguard Worker {
1189*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("_httpTLSWrite: EncryptMessage failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), scRet)));
1190*5e7646d2SAndroid Build Coastguard Worker WSASetLastError(WSASYSCALLFAILURE);
1191*5e7646d2SAndroid Build Coastguard Worker return (-1);
1192*5e7646d2SAndroid Build Coastguard Worker }
1193*5e7646d2SAndroid Build Coastguard Worker
1194*5e7646d2SAndroid Build Coastguard Worker /*
1195*5e7646d2SAndroid Build Coastguard Worker * Send the data. Remember the size of the total data to send is the size
1196*5e7646d2SAndroid Build Coastguard Worker * of the header, the size of the data the caller passed in and the size
1197*5e7646d2SAndroid Build Coastguard Worker * of the trailer...
1198*5e7646d2SAndroid Build Coastguard Worker */
1199*5e7646d2SAndroid Build Coastguard Worker
1200*5e7646d2SAndroid Build Coastguard Worker num = send(http->fd, sspi->writeBuffer, buffers[0].cbBuffer + buffers[1].cbBuffer + buffers[2].cbBuffer, 0);
1201*5e7646d2SAndroid Build Coastguard Worker
1202*5e7646d2SAndroid Build Coastguard Worker if (num <= 0)
1203*5e7646d2SAndroid Build Coastguard Worker {
1204*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("_httpTLSWrite: send failed: %ld", WSAGetLastError()));
1205*5e7646d2SAndroid Build Coastguard Worker return (num);
1206*5e7646d2SAndroid Build Coastguard Worker }
1207*5e7646d2SAndroid Build Coastguard Worker
1208*5e7646d2SAndroid Build Coastguard Worker bytesLeft -= chunk;
1209*5e7646d2SAndroid Build Coastguard Worker bufptr += chunk;
1210*5e7646d2SAndroid Build Coastguard Worker }
1211*5e7646d2SAndroid Build Coastguard Worker
1212*5e7646d2SAndroid Build Coastguard Worker return (len);
1213*5e7646d2SAndroid Build Coastguard Worker }
1214*5e7646d2SAndroid Build Coastguard Worker
1215*5e7646d2SAndroid Build Coastguard Worker
1216*5e7646d2SAndroid Build Coastguard Worker #if 0
1217*5e7646d2SAndroid Build Coastguard Worker /*
1218*5e7646d2SAndroid Build Coastguard Worker * 'http_setup_ssl()' - Set up SSL/TLS support on a connection.
1219*5e7646d2SAndroid Build Coastguard Worker */
1220*5e7646d2SAndroid Build Coastguard Worker
1221*5e7646d2SAndroid Build Coastguard Worker static int /* O - 0 on success, -1 on failure */
1222*5e7646d2SAndroid Build Coastguard Worker http_setup_ssl(http_t *http) /* I - Connection to server */
1223*5e7646d2SAndroid Build Coastguard Worker {
1224*5e7646d2SAndroid Build Coastguard Worker char hostname[256], /* Hostname */
1225*5e7646d2SAndroid Build Coastguard Worker *hostptr; /* Pointer into hostname */
1226*5e7646d2SAndroid Build Coastguard Worker
1227*5e7646d2SAndroid Build Coastguard Worker TCHAR username[256]; /* Username returned from GetUserName() */
1228*5e7646d2SAndroid Build Coastguard Worker TCHAR commonName[256];/* Common name for certificate */
1229*5e7646d2SAndroid Build Coastguard Worker DWORD dwSize; /* 32 bit size */
1230*5e7646d2SAndroid Build Coastguard Worker
1231*5e7646d2SAndroid Build Coastguard Worker
1232*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("7http_setup_ssl(http=%p)", http));
1233*5e7646d2SAndroid Build Coastguard Worker
1234*5e7646d2SAndroid Build Coastguard Worker /*
1235*5e7646d2SAndroid Build Coastguard Worker * Get the hostname to use for SSL...
1236*5e7646d2SAndroid Build Coastguard Worker */
1237*5e7646d2SAndroid Build Coastguard Worker
1238*5e7646d2SAndroid Build Coastguard Worker if (httpAddrLocalhost(http->hostaddr))
1239*5e7646d2SAndroid Build Coastguard Worker {
1240*5e7646d2SAndroid Build Coastguard Worker strlcpy(hostname, "localhost", sizeof(hostname));
1241*5e7646d2SAndroid Build Coastguard Worker }
1242*5e7646d2SAndroid Build Coastguard Worker else
1243*5e7646d2SAndroid Build Coastguard Worker {
1244*5e7646d2SAndroid Build Coastguard Worker /*
1245*5e7646d2SAndroid Build Coastguard Worker * Otherwise make sure the hostname we have does not end in a trailing dot.
1246*5e7646d2SAndroid Build Coastguard Worker */
1247*5e7646d2SAndroid Build Coastguard Worker
1248*5e7646d2SAndroid Build Coastguard Worker strlcpy(hostname, http->hostname, sizeof(hostname));
1249*5e7646d2SAndroid Build Coastguard Worker if ((hostptr = hostname + strlen(hostname) - 1) >= hostname &&
1250*5e7646d2SAndroid Build Coastguard Worker *hostptr == '.')
1251*5e7646d2SAndroid Build Coastguard Worker *hostptr = '\0';
1252*5e7646d2SAndroid Build Coastguard Worker }
1253*5e7646d2SAndroid Build Coastguard Worker
1254*5e7646d2SAndroid Build Coastguard Worker http->tls = http_sspi_alloc();
1255*5e7646d2SAndroid Build Coastguard Worker
1256*5e7646d2SAndroid Build Coastguard Worker if (!http->tls)
1257*5e7646d2SAndroid Build Coastguard Worker {
1258*5e7646d2SAndroid Build Coastguard Worker _cupsSetHTTPError(HTTP_STATUS_ERROR);
1259*5e7646d2SAndroid Build Coastguard Worker return (-1);
1260*5e7646d2SAndroid Build Coastguard Worker }
1261*5e7646d2SAndroid Build Coastguard Worker
1262*5e7646d2SAndroid Build Coastguard Worker dwSize = sizeof(username) / sizeof(TCHAR);
1263*5e7646d2SAndroid Build Coastguard Worker GetUserName(username, &dwSize);
1264*5e7646d2SAndroid Build Coastguard Worker _sntprintf_s(commonName, sizeof(commonName) / sizeof(TCHAR),
1265*5e7646d2SAndroid Build Coastguard Worker sizeof(commonName) / sizeof(TCHAR), TEXT("CN=%s"), username);
1266*5e7646d2SAndroid Build Coastguard Worker
1267*5e7646d2SAndroid Build Coastguard Worker if (!_sspiGetCredentials(http->tls, L"ClientContainer",
1268*5e7646d2SAndroid Build Coastguard Worker commonName, FALSE))
1269*5e7646d2SAndroid Build Coastguard Worker {
1270*5e7646d2SAndroid Build Coastguard Worker _sspiFree(http->tls);
1271*5e7646d2SAndroid Build Coastguard Worker http->tls = NULL;
1272*5e7646d2SAndroid Build Coastguard Worker
1273*5e7646d2SAndroid Build Coastguard Worker http->error = EIO;
1274*5e7646d2SAndroid Build Coastguard Worker http->status = HTTP_STATUS_ERROR;
1275*5e7646d2SAndroid Build Coastguard Worker
1276*5e7646d2SAndroid Build Coastguard Worker _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI,
1277*5e7646d2SAndroid Build Coastguard Worker _("Unable to establish a secure connection to host."), 1);
1278*5e7646d2SAndroid Build Coastguard Worker
1279*5e7646d2SAndroid Build Coastguard Worker return (-1);
1280*5e7646d2SAndroid Build Coastguard Worker }
1281*5e7646d2SAndroid Build Coastguard Worker
1282*5e7646d2SAndroid Build Coastguard Worker _sspiSetAllowsAnyRoot(http->tls, TRUE);
1283*5e7646d2SAndroid Build Coastguard Worker _sspiSetAllowsExpiredCerts(http->tls, TRUE);
1284*5e7646d2SAndroid Build Coastguard Worker
1285*5e7646d2SAndroid Build Coastguard Worker if (!_sspiConnect(http->tls, hostname))
1286*5e7646d2SAndroid Build Coastguard Worker {
1287*5e7646d2SAndroid Build Coastguard Worker _sspiFree(http->tls);
1288*5e7646d2SAndroid Build Coastguard Worker http->tls = NULL;
1289*5e7646d2SAndroid Build Coastguard Worker
1290*5e7646d2SAndroid Build Coastguard Worker http->error = EIO;
1291*5e7646d2SAndroid Build Coastguard Worker http->status = HTTP_STATUS_ERROR;
1292*5e7646d2SAndroid Build Coastguard Worker
1293*5e7646d2SAndroid Build Coastguard Worker _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI,
1294*5e7646d2SAndroid Build Coastguard Worker _("Unable to establish a secure connection to host."), 1);
1295*5e7646d2SAndroid Build Coastguard Worker
1296*5e7646d2SAndroid Build Coastguard Worker return (-1);
1297*5e7646d2SAndroid Build Coastguard Worker }
1298*5e7646d2SAndroid Build Coastguard Worker
1299*5e7646d2SAndroid Build Coastguard Worker return (0);
1300*5e7646d2SAndroid Build Coastguard Worker }
1301*5e7646d2SAndroid Build Coastguard Worker #endif // 0
1302*5e7646d2SAndroid Build Coastguard Worker
1303*5e7646d2SAndroid Build Coastguard Worker
1304*5e7646d2SAndroid Build Coastguard Worker /*
1305*5e7646d2SAndroid Build Coastguard Worker * 'http_sspi_alloc()' - Allocate SSPI object.
1306*5e7646d2SAndroid Build Coastguard Worker */
1307*5e7646d2SAndroid Build Coastguard Worker
1308*5e7646d2SAndroid Build Coastguard Worker static _http_sspi_t * /* O - New SSPI/SSL object */
http_sspi_alloc(void)1309*5e7646d2SAndroid Build Coastguard Worker http_sspi_alloc(void)
1310*5e7646d2SAndroid Build Coastguard Worker {
1311*5e7646d2SAndroid Build Coastguard Worker return ((_http_sspi_t *)calloc(sizeof(_http_sspi_t), 1));
1312*5e7646d2SAndroid Build Coastguard Worker }
1313*5e7646d2SAndroid Build Coastguard Worker
1314*5e7646d2SAndroid Build Coastguard Worker
1315*5e7646d2SAndroid Build Coastguard Worker /*
1316*5e7646d2SAndroid Build Coastguard Worker * 'http_sspi_client()' - Negotiate a TLS connection as a client.
1317*5e7646d2SAndroid Build Coastguard Worker */
1318*5e7646d2SAndroid Build Coastguard Worker
1319*5e7646d2SAndroid Build Coastguard Worker static int /* O - 0 on success, -1 on failure */
http_sspi_client(http_t * http,const char * hostname)1320*5e7646d2SAndroid Build Coastguard Worker http_sspi_client(http_t *http, /* I - Client connection */
1321*5e7646d2SAndroid Build Coastguard Worker const char *hostname) /* I - Server hostname */
1322*5e7646d2SAndroid Build Coastguard Worker {
1323*5e7646d2SAndroid Build Coastguard Worker _http_sspi_t *sspi = http->tls; /* SSPI data */
1324*5e7646d2SAndroid Build Coastguard Worker DWORD dwSize; /* Size for buffer */
1325*5e7646d2SAndroid Build Coastguard Worker DWORD dwSSPIFlags; /* SSL connection attributes we want */
1326*5e7646d2SAndroid Build Coastguard Worker DWORD dwSSPIOutFlags; /* SSL connection attributes we got */
1327*5e7646d2SAndroid Build Coastguard Worker TimeStamp tsExpiry; /* Time stamp */
1328*5e7646d2SAndroid Build Coastguard Worker SECURITY_STATUS scRet; /* Status */
1329*5e7646d2SAndroid Build Coastguard Worker int cbData; /* Data count */
1330*5e7646d2SAndroid Build Coastguard Worker SecBufferDesc inBuffer; /* Array of SecBuffer structs */
1331*5e7646d2SAndroid Build Coastguard Worker SecBuffer inBuffers[2]; /* Security package buffer */
1332*5e7646d2SAndroid Build Coastguard Worker SecBufferDesc outBuffer; /* Array of SecBuffer structs */
1333*5e7646d2SAndroid Build Coastguard Worker SecBuffer outBuffers[1]; /* Security package buffer */
1334*5e7646d2SAndroid Build Coastguard Worker int ret = 0; /* Return value */
1335*5e7646d2SAndroid Build Coastguard Worker
1336*5e7646d2SAndroid Build Coastguard Worker
1337*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4http_sspi_client(http=%p, hostname=\"%s\")", http, hostname));
1338*5e7646d2SAndroid Build Coastguard Worker
1339*5e7646d2SAndroid Build Coastguard Worker dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT |
1340*5e7646d2SAndroid Build Coastguard Worker ISC_REQ_REPLAY_DETECT |
1341*5e7646d2SAndroid Build Coastguard Worker ISC_REQ_CONFIDENTIALITY |
1342*5e7646d2SAndroid Build Coastguard Worker ISC_RET_EXTENDED_ERROR |
1343*5e7646d2SAndroid Build Coastguard Worker ISC_REQ_ALLOCATE_MEMORY |
1344*5e7646d2SAndroid Build Coastguard Worker ISC_REQ_STREAM;
1345*5e7646d2SAndroid Build Coastguard Worker
1346*5e7646d2SAndroid Build Coastguard Worker /*
1347*5e7646d2SAndroid Build Coastguard Worker * Lookup the client certificate...
1348*5e7646d2SAndroid Build Coastguard Worker */
1349*5e7646d2SAndroid Build Coastguard Worker
1350*5e7646d2SAndroid Build Coastguard Worker if (!http_sspi_find_credentials(http, L"ClientContainer", NULL))
1351*5e7646d2SAndroid Build Coastguard Worker {
1352*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5http_sspi_client: Unable to get client credentials.");
1353*5e7646d2SAndroid Build Coastguard Worker return (-1);
1354*5e7646d2SAndroid Build Coastguard Worker }
1355*5e7646d2SAndroid Build Coastguard Worker
1356*5e7646d2SAndroid Build Coastguard Worker /*
1357*5e7646d2SAndroid Build Coastguard Worker * Initiate a ClientHello message and generate a token.
1358*5e7646d2SAndroid Build Coastguard Worker */
1359*5e7646d2SAndroid Build Coastguard Worker
1360*5e7646d2SAndroid Build Coastguard Worker outBuffers[0].pvBuffer = NULL;
1361*5e7646d2SAndroid Build Coastguard Worker outBuffers[0].BufferType = SECBUFFER_TOKEN;
1362*5e7646d2SAndroid Build Coastguard Worker outBuffers[0].cbBuffer = 0;
1363*5e7646d2SAndroid Build Coastguard Worker
1364*5e7646d2SAndroid Build Coastguard Worker outBuffer.cBuffers = 1;
1365*5e7646d2SAndroid Build Coastguard Worker outBuffer.pBuffers = outBuffers;
1366*5e7646d2SAndroid Build Coastguard Worker outBuffer.ulVersion = SECBUFFER_VERSION;
1367*5e7646d2SAndroid Build Coastguard Worker
1368*5e7646d2SAndroid Build Coastguard Worker scRet = InitializeSecurityContext(&sspi->creds, NULL, TEXT(""), dwSSPIFlags, 0, SECURITY_NATIVE_DREP, NULL, 0, &sspi->context, &outBuffer, &dwSSPIOutFlags, &tsExpiry);
1369*5e7646d2SAndroid Build Coastguard Worker
1370*5e7646d2SAndroid Build Coastguard Worker if (scRet != SEC_I_CONTINUE_NEEDED)
1371*5e7646d2SAndroid Build Coastguard Worker {
1372*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_client: InitializeSecurityContext(1) failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), scRet)));
1373*5e7646d2SAndroid Build Coastguard Worker return (-1);
1374*5e7646d2SAndroid Build Coastguard Worker }
1375*5e7646d2SAndroid Build Coastguard Worker
1376*5e7646d2SAndroid Build Coastguard Worker /*
1377*5e7646d2SAndroid Build Coastguard Worker * Send response to server if there is one.
1378*5e7646d2SAndroid Build Coastguard Worker */
1379*5e7646d2SAndroid Build Coastguard Worker
1380*5e7646d2SAndroid Build Coastguard Worker if (outBuffers[0].cbBuffer && outBuffers[0].pvBuffer)
1381*5e7646d2SAndroid Build Coastguard Worker {
1382*5e7646d2SAndroid Build Coastguard Worker if ((cbData = send(http->fd, outBuffers[0].pvBuffer, outBuffers[0].cbBuffer, 0)) <= 0)
1383*5e7646d2SAndroid Build Coastguard Worker {
1384*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_client: send failed: %d", WSAGetLastError()));
1385*5e7646d2SAndroid Build Coastguard Worker FreeContextBuffer(outBuffers[0].pvBuffer);
1386*5e7646d2SAndroid Build Coastguard Worker DeleteSecurityContext(&sspi->context);
1387*5e7646d2SAndroid Build Coastguard Worker return (-1);
1388*5e7646d2SAndroid Build Coastguard Worker }
1389*5e7646d2SAndroid Build Coastguard Worker
1390*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_client: %d bytes of handshake data sent.", cbData));
1391*5e7646d2SAndroid Build Coastguard Worker
1392*5e7646d2SAndroid Build Coastguard Worker FreeContextBuffer(outBuffers[0].pvBuffer);
1393*5e7646d2SAndroid Build Coastguard Worker outBuffers[0].pvBuffer = NULL;
1394*5e7646d2SAndroid Build Coastguard Worker }
1395*5e7646d2SAndroid Build Coastguard Worker
1396*5e7646d2SAndroid Build Coastguard Worker dwSSPIFlags = ISC_REQ_MANUAL_CRED_VALIDATION |
1397*5e7646d2SAndroid Build Coastguard Worker ISC_REQ_SEQUENCE_DETECT |
1398*5e7646d2SAndroid Build Coastguard Worker ISC_REQ_REPLAY_DETECT |
1399*5e7646d2SAndroid Build Coastguard Worker ISC_REQ_CONFIDENTIALITY |
1400*5e7646d2SAndroid Build Coastguard Worker ISC_RET_EXTENDED_ERROR |
1401*5e7646d2SAndroid Build Coastguard Worker ISC_REQ_ALLOCATE_MEMORY |
1402*5e7646d2SAndroid Build Coastguard Worker ISC_REQ_STREAM;
1403*5e7646d2SAndroid Build Coastguard Worker
1404*5e7646d2SAndroid Build Coastguard Worker sspi->decryptBufferUsed = 0;
1405*5e7646d2SAndroid Build Coastguard Worker
1406*5e7646d2SAndroid Build Coastguard Worker /*
1407*5e7646d2SAndroid Build Coastguard Worker * Loop until the handshake is finished or an error occurs.
1408*5e7646d2SAndroid Build Coastguard Worker */
1409*5e7646d2SAndroid Build Coastguard Worker
1410*5e7646d2SAndroid Build Coastguard Worker scRet = SEC_I_CONTINUE_NEEDED;
1411*5e7646d2SAndroid Build Coastguard Worker
1412*5e7646d2SAndroid Build Coastguard Worker while(scRet == SEC_I_CONTINUE_NEEDED ||
1413*5e7646d2SAndroid Build Coastguard Worker scRet == SEC_E_INCOMPLETE_MESSAGE ||
1414*5e7646d2SAndroid Build Coastguard Worker scRet == SEC_I_INCOMPLETE_CREDENTIALS)
1415*5e7646d2SAndroid Build Coastguard Worker {
1416*5e7646d2SAndroid Build Coastguard Worker if (sspi->decryptBufferUsed == 0 || scRet == SEC_E_INCOMPLETE_MESSAGE)
1417*5e7646d2SAndroid Build Coastguard Worker {
1418*5e7646d2SAndroid Build Coastguard Worker if (sspi->decryptBufferLength <= sspi->decryptBufferUsed)
1419*5e7646d2SAndroid Build Coastguard Worker {
1420*5e7646d2SAndroid Build Coastguard Worker BYTE *temp; /* New buffer */
1421*5e7646d2SAndroid Build Coastguard Worker
1422*5e7646d2SAndroid Build Coastguard Worker if (sspi->decryptBufferLength >= 262144)
1423*5e7646d2SAndroid Build Coastguard Worker {
1424*5e7646d2SAndroid Build Coastguard Worker WSASetLastError(E_OUTOFMEMORY);
1425*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5http_sspi_client: Decryption buffer too large (>256k)");
1426*5e7646d2SAndroid Build Coastguard Worker return (-1);
1427*5e7646d2SAndroid Build Coastguard Worker }
1428*5e7646d2SAndroid Build Coastguard Worker
1429*5e7646d2SAndroid Build Coastguard Worker if ((temp = realloc(sspi->decryptBuffer, sspi->decryptBufferLength + 4096)) == NULL)
1430*5e7646d2SAndroid Build Coastguard Worker {
1431*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_client: Unable to allocate %d byte buffer.", sspi->decryptBufferLength + 4096));
1432*5e7646d2SAndroid Build Coastguard Worker WSASetLastError(E_OUTOFMEMORY);
1433*5e7646d2SAndroid Build Coastguard Worker return (-1);
1434*5e7646d2SAndroid Build Coastguard Worker }
1435*5e7646d2SAndroid Build Coastguard Worker
1436*5e7646d2SAndroid Build Coastguard Worker sspi->decryptBufferLength += 4096;
1437*5e7646d2SAndroid Build Coastguard Worker sspi->decryptBuffer = temp;
1438*5e7646d2SAndroid Build Coastguard Worker }
1439*5e7646d2SAndroid Build Coastguard Worker
1440*5e7646d2SAndroid Build Coastguard Worker cbData = recv(http->fd, sspi->decryptBuffer + sspi->decryptBufferUsed, (int)(sspi->decryptBufferLength - sspi->decryptBufferUsed), 0);
1441*5e7646d2SAndroid Build Coastguard Worker
1442*5e7646d2SAndroid Build Coastguard Worker if (cbData < 0)
1443*5e7646d2SAndroid Build Coastguard Worker {
1444*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_client: recv failed: %d", WSAGetLastError()));
1445*5e7646d2SAndroid Build Coastguard Worker return (-1);
1446*5e7646d2SAndroid Build Coastguard Worker }
1447*5e7646d2SAndroid Build Coastguard Worker else if (cbData == 0)
1448*5e7646d2SAndroid Build Coastguard Worker {
1449*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_client: Server unexpectedly disconnected."));
1450*5e7646d2SAndroid Build Coastguard Worker return (-1);
1451*5e7646d2SAndroid Build Coastguard Worker }
1452*5e7646d2SAndroid Build Coastguard Worker
1453*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_client: %d bytes of handshake data received", cbData));
1454*5e7646d2SAndroid Build Coastguard Worker
1455*5e7646d2SAndroid Build Coastguard Worker sspi->decryptBufferUsed += cbData;
1456*5e7646d2SAndroid Build Coastguard Worker }
1457*5e7646d2SAndroid Build Coastguard Worker
1458*5e7646d2SAndroid Build Coastguard Worker /*
1459*5e7646d2SAndroid Build Coastguard Worker * Set up the input buffers. Buffer 0 is used to pass in data received from
1460*5e7646d2SAndroid Build Coastguard Worker * the server. Schannel will consume some or all of this. Leftover data
1461*5e7646d2SAndroid Build Coastguard Worker * (if any) will be placed in buffer 1 and given a buffer type of
1462*5e7646d2SAndroid Build Coastguard Worker * SECBUFFER_EXTRA.
1463*5e7646d2SAndroid Build Coastguard Worker */
1464*5e7646d2SAndroid Build Coastguard Worker
1465*5e7646d2SAndroid Build Coastguard Worker inBuffers[0].pvBuffer = sspi->decryptBuffer;
1466*5e7646d2SAndroid Build Coastguard Worker inBuffers[0].cbBuffer = (unsigned long)sspi->decryptBufferUsed;
1467*5e7646d2SAndroid Build Coastguard Worker inBuffers[0].BufferType = SECBUFFER_TOKEN;
1468*5e7646d2SAndroid Build Coastguard Worker
1469*5e7646d2SAndroid Build Coastguard Worker inBuffers[1].pvBuffer = NULL;
1470*5e7646d2SAndroid Build Coastguard Worker inBuffers[1].cbBuffer = 0;
1471*5e7646d2SAndroid Build Coastguard Worker inBuffers[1].BufferType = SECBUFFER_EMPTY;
1472*5e7646d2SAndroid Build Coastguard Worker
1473*5e7646d2SAndroid Build Coastguard Worker inBuffer.cBuffers = 2;
1474*5e7646d2SAndroid Build Coastguard Worker inBuffer.pBuffers = inBuffers;
1475*5e7646d2SAndroid Build Coastguard Worker inBuffer.ulVersion = SECBUFFER_VERSION;
1476*5e7646d2SAndroid Build Coastguard Worker
1477*5e7646d2SAndroid Build Coastguard Worker /*
1478*5e7646d2SAndroid Build Coastguard Worker * Set up the output buffers. These are initialized to NULL so as to make it
1479*5e7646d2SAndroid Build Coastguard Worker * less likely we'll attempt to free random garbage later.
1480*5e7646d2SAndroid Build Coastguard Worker */
1481*5e7646d2SAndroid Build Coastguard Worker
1482*5e7646d2SAndroid Build Coastguard Worker outBuffers[0].pvBuffer = NULL;
1483*5e7646d2SAndroid Build Coastguard Worker outBuffers[0].BufferType = SECBUFFER_TOKEN;
1484*5e7646d2SAndroid Build Coastguard Worker outBuffers[0].cbBuffer = 0;
1485*5e7646d2SAndroid Build Coastguard Worker
1486*5e7646d2SAndroid Build Coastguard Worker outBuffer.cBuffers = 1;
1487*5e7646d2SAndroid Build Coastguard Worker outBuffer.pBuffers = outBuffers;
1488*5e7646d2SAndroid Build Coastguard Worker outBuffer.ulVersion = SECBUFFER_VERSION;
1489*5e7646d2SAndroid Build Coastguard Worker
1490*5e7646d2SAndroid Build Coastguard Worker /*
1491*5e7646d2SAndroid Build Coastguard Worker * Call InitializeSecurityContext.
1492*5e7646d2SAndroid Build Coastguard Worker */
1493*5e7646d2SAndroid Build Coastguard Worker
1494*5e7646d2SAndroid Build Coastguard Worker scRet = InitializeSecurityContext(&sspi->creds, &sspi->context, NULL, dwSSPIFlags, 0, SECURITY_NATIVE_DREP, &inBuffer, 0, NULL, &outBuffer, &dwSSPIOutFlags, &tsExpiry);
1495*5e7646d2SAndroid Build Coastguard Worker
1496*5e7646d2SAndroid Build Coastguard Worker /*
1497*5e7646d2SAndroid Build Coastguard Worker * If InitializeSecurityContext was successful (or if the error was one of
1498*5e7646d2SAndroid Build Coastguard Worker * the special extended ones), send the contents of the output buffer to the
1499*5e7646d2SAndroid Build Coastguard Worker * server.
1500*5e7646d2SAndroid Build Coastguard Worker */
1501*5e7646d2SAndroid Build Coastguard Worker
1502*5e7646d2SAndroid Build Coastguard Worker if (scRet == SEC_E_OK ||
1503*5e7646d2SAndroid Build Coastguard Worker scRet == SEC_I_CONTINUE_NEEDED ||
1504*5e7646d2SAndroid Build Coastguard Worker FAILED(scRet) && (dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR))
1505*5e7646d2SAndroid Build Coastguard Worker {
1506*5e7646d2SAndroid Build Coastguard Worker if (outBuffers[0].cbBuffer && outBuffers[0].pvBuffer)
1507*5e7646d2SAndroid Build Coastguard Worker {
1508*5e7646d2SAndroid Build Coastguard Worker cbData = send(http->fd, outBuffers[0].pvBuffer, outBuffers[0].cbBuffer, 0);
1509*5e7646d2SAndroid Build Coastguard Worker
1510*5e7646d2SAndroid Build Coastguard Worker if (cbData <= 0)
1511*5e7646d2SAndroid Build Coastguard Worker {
1512*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_client: send failed: %d", WSAGetLastError()));
1513*5e7646d2SAndroid Build Coastguard Worker FreeContextBuffer(outBuffers[0].pvBuffer);
1514*5e7646d2SAndroid Build Coastguard Worker DeleteSecurityContext(&sspi->context);
1515*5e7646d2SAndroid Build Coastguard Worker return (-1);
1516*5e7646d2SAndroid Build Coastguard Worker }
1517*5e7646d2SAndroid Build Coastguard Worker
1518*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_client: %d bytes of handshake data sent.", cbData));
1519*5e7646d2SAndroid Build Coastguard Worker
1520*5e7646d2SAndroid Build Coastguard Worker /*
1521*5e7646d2SAndroid Build Coastguard Worker * Free output buffer.
1522*5e7646d2SAndroid Build Coastguard Worker */
1523*5e7646d2SAndroid Build Coastguard Worker
1524*5e7646d2SAndroid Build Coastguard Worker FreeContextBuffer(outBuffers[0].pvBuffer);
1525*5e7646d2SAndroid Build Coastguard Worker outBuffers[0].pvBuffer = NULL;
1526*5e7646d2SAndroid Build Coastguard Worker }
1527*5e7646d2SAndroid Build Coastguard Worker }
1528*5e7646d2SAndroid Build Coastguard Worker
1529*5e7646d2SAndroid Build Coastguard Worker /*
1530*5e7646d2SAndroid Build Coastguard Worker * If InitializeSecurityContext returned SEC_E_INCOMPLETE_MESSAGE, then we
1531*5e7646d2SAndroid Build Coastguard Worker * need to read more data from the server and try again.
1532*5e7646d2SAndroid Build Coastguard Worker */
1533*5e7646d2SAndroid Build Coastguard Worker
1534*5e7646d2SAndroid Build Coastguard Worker if (scRet == SEC_E_INCOMPLETE_MESSAGE)
1535*5e7646d2SAndroid Build Coastguard Worker continue;
1536*5e7646d2SAndroid Build Coastguard Worker
1537*5e7646d2SAndroid Build Coastguard Worker /*
1538*5e7646d2SAndroid Build Coastguard Worker * If InitializeSecurityContext returned SEC_E_OK, then the handshake
1539*5e7646d2SAndroid Build Coastguard Worker * completed successfully.
1540*5e7646d2SAndroid Build Coastguard Worker */
1541*5e7646d2SAndroid Build Coastguard Worker
1542*5e7646d2SAndroid Build Coastguard Worker if (scRet == SEC_E_OK)
1543*5e7646d2SAndroid Build Coastguard Worker {
1544*5e7646d2SAndroid Build Coastguard Worker /*
1545*5e7646d2SAndroid Build Coastguard Worker * If the "extra" buffer contains data, this is encrypted application
1546*5e7646d2SAndroid Build Coastguard Worker * protocol layer stuff. It needs to be saved. The application layer will
1547*5e7646d2SAndroid Build Coastguard Worker * later decrypt it with DecryptMessage.
1548*5e7646d2SAndroid Build Coastguard Worker */
1549*5e7646d2SAndroid Build Coastguard Worker
1550*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5http_sspi_client: Handshake was successful.");
1551*5e7646d2SAndroid Build Coastguard Worker
1552*5e7646d2SAndroid Build Coastguard Worker if (inBuffers[1].BufferType == SECBUFFER_EXTRA)
1553*5e7646d2SAndroid Build Coastguard Worker {
1554*5e7646d2SAndroid Build Coastguard Worker memmove(sspi->decryptBuffer, sspi->decryptBuffer + sspi->decryptBufferUsed - inBuffers[1].cbBuffer, inBuffers[1].cbBuffer);
1555*5e7646d2SAndroid Build Coastguard Worker
1556*5e7646d2SAndroid Build Coastguard Worker sspi->decryptBufferUsed = inBuffers[1].cbBuffer;
1557*5e7646d2SAndroid Build Coastguard Worker
1558*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_client: %d bytes of app data was bundled with handshake data", sspi->decryptBufferUsed));
1559*5e7646d2SAndroid Build Coastguard Worker }
1560*5e7646d2SAndroid Build Coastguard Worker else
1561*5e7646d2SAndroid Build Coastguard Worker sspi->decryptBufferUsed = 0;
1562*5e7646d2SAndroid Build Coastguard Worker
1563*5e7646d2SAndroid Build Coastguard Worker /*
1564*5e7646d2SAndroid Build Coastguard Worker * Bail out to quit
1565*5e7646d2SAndroid Build Coastguard Worker */
1566*5e7646d2SAndroid Build Coastguard Worker
1567*5e7646d2SAndroid Build Coastguard Worker break;
1568*5e7646d2SAndroid Build Coastguard Worker }
1569*5e7646d2SAndroid Build Coastguard Worker
1570*5e7646d2SAndroid Build Coastguard Worker /*
1571*5e7646d2SAndroid Build Coastguard Worker * Check for fatal error.
1572*5e7646d2SAndroid Build Coastguard Worker */
1573*5e7646d2SAndroid Build Coastguard Worker
1574*5e7646d2SAndroid Build Coastguard Worker if (FAILED(scRet))
1575*5e7646d2SAndroid Build Coastguard Worker {
1576*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_client: InitializeSecurityContext(2) failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), scRet)));
1577*5e7646d2SAndroid Build Coastguard Worker ret = -1;
1578*5e7646d2SAndroid Build Coastguard Worker break;
1579*5e7646d2SAndroid Build Coastguard Worker }
1580*5e7646d2SAndroid Build Coastguard Worker
1581*5e7646d2SAndroid Build Coastguard Worker /*
1582*5e7646d2SAndroid Build Coastguard Worker * If InitializeSecurityContext returned SEC_I_INCOMPLETE_CREDENTIALS,
1583*5e7646d2SAndroid Build Coastguard Worker * then the server just requested client authentication.
1584*5e7646d2SAndroid Build Coastguard Worker */
1585*5e7646d2SAndroid Build Coastguard Worker
1586*5e7646d2SAndroid Build Coastguard Worker if (scRet == SEC_I_INCOMPLETE_CREDENTIALS)
1587*5e7646d2SAndroid Build Coastguard Worker {
1588*5e7646d2SAndroid Build Coastguard Worker /*
1589*5e7646d2SAndroid Build Coastguard Worker * Unimplemented
1590*5e7646d2SAndroid Build Coastguard Worker */
1591*5e7646d2SAndroid Build Coastguard Worker
1592*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_client: server requested client credentials."));
1593*5e7646d2SAndroid Build Coastguard Worker ret = -1;
1594*5e7646d2SAndroid Build Coastguard Worker break;
1595*5e7646d2SAndroid Build Coastguard Worker }
1596*5e7646d2SAndroid Build Coastguard Worker
1597*5e7646d2SAndroid Build Coastguard Worker /*
1598*5e7646d2SAndroid Build Coastguard Worker * Copy any leftover data from the "extra" buffer, and go around again.
1599*5e7646d2SAndroid Build Coastguard Worker */
1600*5e7646d2SAndroid Build Coastguard Worker
1601*5e7646d2SAndroid Build Coastguard Worker if (inBuffers[1].BufferType == SECBUFFER_EXTRA)
1602*5e7646d2SAndroid Build Coastguard Worker {
1603*5e7646d2SAndroid Build Coastguard Worker memmove(sspi->decryptBuffer, sspi->decryptBuffer + sspi->decryptBufferUsed - inBuffers[1].cbBuffer, inBuffers[1].cbBuffer);
1604*5e7646d2SAndroid Build Coastguard Worker
1605*5e7646d2SAndroid Build Coastguard Worker sspi->decryptBufferUsed = inBuffers[1].cbBuffer;
1606*5e7646d2SAndroid Build Coastguard Worker }
1607*5e7646d2SAndroid Build Coastguard Worker else
1608*5e7646d2SAndroid Build Coastguard Worker {
1609*5e7646d2SAndroid Build Coastguard Worker sspi->decryptBufferUsed = 0;
1610*5e7646d2SAndroid Build Coastguard Worker }
1611*5e7646d2SAndroid Build Coastguard Worker }
1612*5e7646d2SAndroid Build Coastguard Worker
1613*5e7646d2SAndroid Build Coastguard Worker if (!ret)
1614*5e7646d2SAndroid Build Coastguard Worker {
1615*5e7646d2SAndroid Build Coastguard Worker /*
1616*5e7646d2SAndroid Build Coastguard Worker * Success! Get the server cert
1617*5e7646d2SAndroid Build Coastguard Worker */
1618*5e7646d2SAndroid Build Coastguard Worker
1619*5e7646d2SAndroid Build Coastguard Worker sspi->contextInitialized = TRUE;
1620*5e7646d2SAndroid Build Coastguard Worker
1621*5e7646d2SAndroid Build Coastguard Worker scRet = QueryContextAttributes(&sspi->context, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (VOID *)&(sspi->remoteCert));
1622*5e7646d2SAndroid Build Coastguard Worker
1623*5e7646d2SAndroid Build Coastguard Worker if (scRet != SEC_E_OK)
1624*5e7646d2SAndroid Build Coastguard Worker {
1625*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_client: QueryContextAttributes failed(SECPKG_ATTR_REMOTE_CERT_CONTEXT): %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), scRet)));
1626*5e7646d2SAndroid Build Coastguard Worker return (-1);
1627*5e7646d2SAndroid Build Coastguard Worker }
1628*5e7646d2SAndroid Build Coastguard Worker
1629*5e7646d2SAndroid Build Coastguard Worker /*
1630*5e7646d2SAndroid Build Coastguard Worker * Find out how big the header/trailer will be:
1631*5e7646d2SAndroid Build Coastguard Worker */
1632*5e7646d2SAndroid Build Coastguard Worker
1633*5e7646d2SAndroid Build Coastguard Worker scRet = QueryContextAttributes(&sspi->context, SECPKG_ATTR_STREAM_SIZES, &sspi->streamSizes);
1634*5e7646d2SAndroid Build Coastguard Worker
1635*5e7646d2SAndroid Build Coastguard Worker if (scRet != SEC_E_OK)
1636*5e7646d2SAndroid Build Coastguard Worker {
1637*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_client: QueryContextAttributes failed(SECPKG_ATTR_STREAM_SIZES): %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), scRet)));
1638*5e7646d2SAndroid Build Coastguard Worker ret = -1;
1639*5e7646d2SAndroid Build Coastguard Worker }
1640*5e7646d2SAndroid Build Coastguard Worker }
1641*5e7646d2SAndroid Build Coastguard Worker
1642*5e7646d2SAndroid Build Coastguard Worker return (ret);
1643*5e7646d2SAndroid Build Coastguard Worker }
1644*5e7646d2SAndroid Build Coastguard Worker
1645*5e7646d2SAndroid Build Coastguard Worker
1646*5e7646d2SAndroid Build Coastguard Worker /*
1647*5e7646d2SAndroid Build Coastguard Worker * 'http_sspi_create_credential()' - Create an SSPI certificate context.
1648*5e7646d2SAndroid Build Coastguard Worker */
1649*5e7646d2SAndroid Build Coastguard Worker
1650*5e7646d2SAndroid Build Coastguard Worker static PCCERT_CONTEXT /* O - Certificate context */
http_sspi_create_credential(http_credential_t * cred)1651*5e7646d2SAndroid Build Coastguard Worker http_sspi_create_credential(
1652*5e7646d2SAndroid Build Coastguard Worker http_credential_t *cred) /* I - Credential */
1653*5e7646d2SAndroid Build Coastguard Worker {
1654*5e7646d2SAndroid Build Coastguard Worker if (cred)
1655*5e7646d2SAndroid Build Coastguard Worker return (CertCreateCertificateContext(X509_ASN_ENCODING, cred->data, cred->datalen));
1656*5e7646d2SAndroid Build Coastguard Worker else
1657*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1658*5e7646d2SAndroid Build Coastguard Worker }
1659*5e7646d2SAndroid Build Coastguard Worker
1660*5e7646d2SAndroid Build Coastguard Worker
1661*5e7646d2SAndroid Build Coastguard Worker /*
1662*5e7646d2SAndroid Build Coastguard Worker * 'http_sspi_find_credentials()' - Retrieve a TLS certificate from the system store.
1663*5e7646d2SAndroid Build Coastguard Worker */
1664*5e7646d2SAndroid Build Coastguard Worker
1665*5e7646d2SAndroid Build Coastguard Worker static BOOL /* O - 1 on success, 0 on failure */
http_sspi_find_credentials(http_t * http,const LPWSTR container,const char * common_name)1666*5e7646d2SAndroid Build Coastguard Worker http_sspi_find_credentials(
1667*5e7646d2SAndroid Build Coastguard Worker http_t *http, /* I - HTTP connection */
1668*5e7646d2SAndroid Build Coastguard Worker const LPWSTR container, /* I - Cert container name */
1669*5e7646d2SAndroid Build Coastguard Worker const char *common_name) /* I - Common name of certificate */
1670*5e7646d2SAndroid Build Coastguard Worker {
1671*5e7646d2SAndroid Build Coastguard Worker _http_sspi_t *sspi = http->tls; /* SSPI data */
1672*5e7646d2SAndroid Build Coastguard Worker HCERTSTORE store = NULL; /* Certificate store */
1673*5e7646d2SAndroid Build Coastguard Worker PCCERT_CONTEXT storedContext = NULL; /* Context created from the store */
1674*5e7646d2SAndroid Build Coastguard Worker DWORD dwSize = 0; /* 32 bit size */
1675*5e7646d2SAndroid Build Coastguard Worker PBYTE p = NULL; /* Temporary storage */
1676*5e7646d2SAndroid Build Coastguard Worker HCRYPTPROV hProv = (HCRYPTPROV)NULL;
1677*5e7646d2SAndroid Build Coastguard Worker /* Handle to a CSP */
1678*5e7646d2SAndroid Build Coastguard Worker CERT_NAME_BLOB sib; /* Arbitrary array of bytes */
1679*5e7646d2SAndroid Build Coastguard Worker SCHANNEL_CRED SchannelCred; /* Schannel credential data */
1680*5e7646d2SAndroid Build Coastguard Worker TimeStamp tsExpiry; /* Time stamp */
1681*5e7646d2SAndroid Build Coastguard Worker SECURITY_STATUS Status; /* Status */
1682*5e7646d2SAndroid Build Coastguard Worker BOOL ok = TRUE; /* Return value */
1683*5e7646d2SAndroid Build Coastguard Worker
1684*5e7646d2SAndroid Build Coastguard Worker
1685*5e7646d2SAndroid Build Coastguard Worker if (!CryptAcquireContextW(&hProv, (LPWSTR)container, MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_MACHINE_KEYSET))
1686*5e7646d2SAndroid Build Coastguard Worker {
1687*5e7646d2SAndroid Build Coastguard Worker if (GetLastError() == NTE_EXISTS)
1688*5e7646d2SAndroid Build Coastguard Worker {
1689*5e7646d2SAndroid Build Coastguard Worker if (!CryptAcquireContextW(&hProv, (LPWSTR)container, MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET))
1690*5e7646d2SAndroid Build Coastguard Worker {
1691*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_find_credentials: CryptAcquireContext failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
1692*5e7646d2SAndroid Build Coastguard Worker ok = FALSE;
1693*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1694*5e7646d2SAndroid Build Coastguard Worker }
1695*5e7646d2SAndroid Build Coastguard Worker }
1696*5e7646d2SAndroid Build Coastguard Worker }
1697*5e7646d2SAndroid Build Coastguard Worker
1698*5e7646d2SAndroid Build Coastguard Worker store = CertOpenStore(CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING|PKCS_7_ASN_ENCODING, hProv, CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_NO_CRYPT_RELEASE_FLAG | CERT_STORE_OPEN_EXISTING_FLAG, L"MY");
1699*5e7646d2SAndroid Build Coastguard Worker
1700*5e7646d2SAndroid Build Coastguard Worker if (!store)
1701*5e7646d2SAndroid Build Coastguard Worker {
1702*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_find_credentials: CertOpenSystemStore failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
1703*5e7646d2SAndroid Build Coastguard Worker ok = FALSE;
1704*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1705*5e7646d2SAndroid Build Coastguard Worker }
1706*5e7646d2SAndroid Build Coastguard Worker
1707*5e7646d2SAndroid Build Coastguard Worker if (common_name)
1708*5e7646d2SAndroid Build Coastguard Worker {
1709*5e7646d2SAndroid Build Coastguard Worker dwSize = 0;
1710*5e7646d2SAndroid Build Coastguard Worker
1711*5e7646d2SAndroid Build Coastguard Worker if (!CertStrToNameA(X509_ASN_ENCODING, common_name, CERT_OID_NAME_STR, NULL, NULL, &dwSize, NULL))
1712*5e7646d2SAndroid Build Coastguard Worker {
1713*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_find_credentials: CertStrToName failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
1714*5e7646d2SAndroid Build Coastguard Worker ok = FALSE;
1715*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1716*5e7646d2SAndroid Build Coastguard Worker }
1717*5e7646d2SAndroid Build Coastguard Worker
1718*5e7646d2SAndroid Build Coastguard Worker p = (PBYTE)malloc(dwSize);
1719*5e7646d2SAndroid Build Coastguard Worker
1720*5e7646d2SAndroid Build Coastguard Worker if (!p)
1721*5e7646d2SAndroid Build Coastguard Worker {
1722*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_find_credentials: malloc failed for %d bytes.", dwSize));
1723*5e7646d2SAndroid Build Coastguard Worker ok = FALSE;
1724*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1725*5e7646d2SAndroid Build Coastguard Worker }
1726*5e7646d2SAndroid Build Coastguard Worker
1727*5e7646d2SAndroid Build Coastguard Worker if (!CertStrToNameA(X509_ASN_ENCODING, common_name, CERT_OID_NAME_STR, NULL, p, &dwSize, NULL))
1728*5e7646d2SAndroid Build Coastguard Worker {
1729*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_find_credentials: CertStrToName failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
1730*5e7646d2SAndroid Build Coastguard Worker ok = FALSE;
1731*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1732*5e7646d2SAndroid Build Coastguard Worker }
1733*5e7646d2SAndroid Build Coastguard Worker
1734*5e7646d2SAndroid Build Coastguard Worker sib.cbData = dwSize;
1735*5e7646d2SAndroid Build Coastguard Worker sib.pbData = p;
1736*5e7646d2SAndroid Build Coastguard Worker
1737*5e7646d2SAndroid Build Coastguard Worker storedContext = CertFindCertificateInStore(store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_NAME, &sib, NULL);
1738*5e7646d2SAndroid Build Coastguard Worker
1739*5e7646d2SAndroid Build Coastguard Worker if (!storedContext)
1740*5e7646d2SAndroid Build Coastguard Worker {
1741*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_find_credentials: Unable to find credentials for \"%s\".", common_name));
1742*5e7646d2SAndroid Build Coastguard Worker ok = FALSE;
1743*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1744*5e7646d2SAndroid Build Coastguard Worker }
1745*5e7646d2SAndroid Build Coastguard Worker }
1746*5e7646d2SAndroid Build Coastguard Worker
1747*5e7646d2SAndroid Build Coastguard Worker ZeroMemory(&SchannelCred, sizeof(SchannelCred));
1748*5e7646d2SAndroid Build Coastguard Worker
1749*5e7646d2SAndroid Build Coastguard Worker SchannelCred.dwVersion = SCHANNEL_CRED_VERSION;
1750*5e7646d2SAndroid Build Coastguard Worker
1751*5e7646d2SAndroid Build Coastguard Worker if (common_name)
1752*5e7646d2SAndroid Build Coastguard Worker {
1753*5e7646d2SAndroid Build Coastguard Worker SchannelCred.cCreds = 1;
1754*5e7646d2SAndroid Build Coastguard Worker SchannelCred.paCred = &storedContext;
1755*5e7646d2SAndroid Build Coastguard Worker }
1756*5e7646d2SAndroid Build Coastguard Worker
1757*5e7646d2SAndroid Build Coastguard Worker /*
1758*5e7646d2SAndroid Build Coastguard Worker * Set supported protocols (can also be overriden in the registry...)
1759*5e7646d2SAndroid Build Coastguard Worker */
1760*5e7646d2SAndroid Build Coastguard Worker
1761*5e7646d2SAndroid Build Coastguard Worker #ifdef SP_PROT_TLS1_2_SERVER
1762*5e7646d2SAndroid Build Coastguard Worker if (http->mode == _HTTP_MODE_SERVER)
1763*5e7646d2SAndroid Build Coastguard Worker {
1764*5e7646d2SAndroid Build Coastguard Worker if (tls_min_version > _HTTP_TLS_1_1)
1765*5e7646d2SAndroid Build Coastguard Worker SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_SERVER;
1766*5e7646d2SAndroid Build Coastguard Worker else if (tls_min_version > _HTTP_TLS_1_0)
1767*5e7646d2SAndroid Build Coastguard Worker SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_SERVER | SP_PROT_TLS1_1_SERVER;
1768*5e7646d2SAndroid Build Coastguard Worker else if (tls_min_version == _HTTP_TLS_SSL3)
1769*5e7646d2SAndroid Build Coastguard Worker SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_SERVER | SP_PROT_TLS1_1_SERVER | SP_PROT_TLS1_0_SERVER | SP_PROT_SSL3_SERVER;
1770*5e7646d2SAndroid Build Coastguard Worker else
1771*5e7646d2SAndroid Build Coastguard Worker SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_SERVER | SP_PROT_TLS1_1_SERVER | SP_PROT_TLS1_0_SERVER;
1772*5e7646d2SAndroid Build Coastguard Worker }
1773*5e7646d2SAndroid Build Coastguard Worker else
1774*5e7646d2SAndroid Build Coastguard Worker {
1775*5e7646d2SAndroid Build Coastguard Worker if (tls_min_version > _HTTP_TLS_1_1)
1776*5e7646d2SAndroid Build Coastguard Worker SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT;
1777*5e7646d2SAndroid Build Coastguard Worker else if (tls_min_version > _HTTP_TLS_1_0)
1778*5e7646d2SAndroid Build Coastguard Worker SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT | SP_PROT_TLS1_1_CLIENT;
1779*5e7646d2SAndroid Build Coastguard Worker else if (tls_min_version == _HTTP_TLS_SSL3)
1780*5e7646d2SAndroid Build Coastguard Worker SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_0_CLIENT | SP_PROT_SSL3_CLIENT;
1781*5e7646d2SAndroid Build Coastguard Worker else
1782*5e7646d2SAndroid Build Coastguard Worker SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_0_CLIENT;
1783*5e7646d2SAndroid Build Coastguard Worker }
1784*5e7646d2SAndroid Build Coastguard Worker
1785*5e7646d2SAndroid Build Coastguard Worker #else
1786*5e7646d2SAndroid Build Coastguard Worker if (http->mode == _HTTP_MODE_SERVER)
1787*5e7646d2SAndroid Build Coastguard Worker {
1788*5e7646d2SAndroid Build Coastguard Worker if (tls_min_version == _HTTP_TLS_SSL3)
1789*5e7646d2SAndroid Build Coastguard Worker SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_SERVER | SP_PROT_SSL3_SERVER;
1790*5e7646d2SAndroid Build Coastguard Worker else
1791*5e7646d2SAndroid Build Coastguard Worker SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_SERVER;
1792*5e7646d2SAndroid Build Coastguard Worker }
1793*5e7646d2SAndroid Build Coastguard Worker else
1794*5e7646d2SAndroid Build Coastguard Worker {
1795*5e7646d2SAndroid Build Coastguard Worker if (tls_min_version == _HTTP_TLS_SSL3)
1796*5e7646d2SAndroid Build Coastguard Worker SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_CLIENT | SP_PROT_SSL3_CLIENT;
1797*5e7646d2SAndroid Build Coastguard Worker else
1798*5e7646d2SAndroid Build Coastguard Worker SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_CLIENT;
1799*5e7646d2SAndroid Build Coastguard Worker }
1800*5e7646d2SAndroid Build Coastguard Worker #endif /* SP_PROT_TLS1_2_SERVER */
1801*5e7646d2SAndroid Build Coastguard Worker
1802*5e7646d2SAndroid Build Coastguard Worker /* TODO: Support _HTTP_TLS_ALLOW_RC4, _HTTP_TLS_ALLOW_DH, and _HTTP_TLS_DENY_CBC options; right now we'll rely on Windows registry to enable/disable RC4/DH/CBC... */
1803*5e7646d2SAndroid Build Coastguard Worker
1804*5e7646d2SAndroid Build Coastguard Worker /*
1805*5e7646d2SAndroid Build Coastguard Worker * Create an SSPI credential.
1806*5e7646d2SAndroid Build Coastguard Worker */
1807*5e7646d2SAndroid Build Coastguard Worker
1808*5e7646d2SAndroid Build Coastguard Worker Status = AcquireCredentialsHandle(NULL, UNISP_NAME, http->mode == _HTTP_MODE_SERVER ? SECPKG_CRED_INBOUND : SECPKG_CRED_OUTBOUND, NULL, &SchannelCred, NULL, NULL, &sspi->creds, &tsExpiry);
1809*5e7646d2SAndroid Build Coastguard Worker if (Status != SEC_E_OK)
1810*5e7646d2SAndroid Build Coastguard Worker {
1811*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_find_credentials: AcquireCredentialsHandle failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), Status)));
1812*5e7646d2SAndroid Build Coastguard Worker ok = FALSE;
1813*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1814*5e7646d2SAndroid Build Coastguard Worker }
1815*5e7646d2SAndroid Build Coastguard Worker
1816*5e7646d2SAndroid Build Coastguard Worker cleanup:
1817*5e7646d2SAndroid Build Coastguard Worker
1818*5e7646d2SAndroid Build Coastguard Worker /*
1819*5e7646d2SAndroid Build Coastguard Worker * Cleanup
1820*5e7646d2SAndroid Build Coastguard Worker */
1821*5e7646d2SAndroid Build Coastguard Worker
1822*5e7646d2SAndroid Build Coastguard Worker if (storedContext)
1823*5e7646d2SAndroid Build Coastguard Worker CertFreeCertificateContext(storedContext);
1824*5e7646d2SAndroid Build Coastguard Worker
1825*5e7646d2SAndroid Build Coastguard Worker if (p)
1826*5e7646d2SAndroid Build Coastguard Worker free(p);
1827*5e7646d2SAndroid Build Coastguard Worker
1828*5e7646d2SAndroid Build Coastguard Worker if (store)
1829*5e7646d2SAndroid Build Coastguard Worker CertCloseStore(store, 0);
1830*5e7646d2SAndroid Build Coastguard Worker
1831*5e7646d2SAndroid Build Coastguard Worker if (hProv)
1832*5e7646d2SAndroid Build Coastguard Worker CryptReleaseContext(hProv, 0);
1833*5e7646d2SAndroid Build Coastguard Worker
1834*5e7646d2SAndroid Build Coastguard Worker return (ok);
1835*5e7646d2SAndroid Build Coastguard Worker }
1836*5e7646d2SAndroid Build Coastguard Worker
1837*5e7646d2SAndroid Build Coastguard Worker
1838*5e7646d2SAndroid Build Coastguard Worker /*
1839*5e7646d2SAndroid Build Coastguard Worker * 'http_sspi_free()' - Close a connection and free resources.
1840*5e7646d2SAndroid Build Coastguard Worker */
1841*5e7646d2SAndroid Build Coastguard Worker
1842*5e7646d2SAndroid Build Coastguard Worker static void
http_sspi_free(_http_sspi_t * sspi)1843*5e7646d2SAndroid Build Coastguard Worker http_sspi_free(_http_sspi_t *sspi) /* I - SSPI data */
1844*5e7646d2SAndroid Build Coastguard Worker {
1845*5e7646d2SAndroid Build Coastguard Worker if (!sspi)
1846*5e7646d2SAndroid Build Coastguard Worker return;
1847*5e7646d2SAndroid Build Coastguard Worker
1848*5e7646d2SAndroid Build Coastguard Worker if (sspi->contextInitialized)
1849*5e7646d2SAndroid Build Coastguard Worker DeleteSecurityContext(&sspi->context);
1850*5e7646d2SAndroid Build Coastguard Worker
1851*5e7646d2SAndroid Build Coastguard Worker if (sspi->decryptBuffer)
1852*5e7646d2SAndroid Build Coastguard Worker free(sspi->decryptBuffer);
1853*5e7646d2SAndroid Build Coastguard Worker
1854*5e7646d2SAndroid Build Coastguard Worker if (sspi->readBuffer)
1855*5e7646d2SAndroid Build Coastguard Worker free(sspi->readBuffer);
1856*5e7646d2SAndroid Build Coastguard Worker
1857*5e7646d2SAndroid Build Coastguard Worker if (sspi->writeBuffer)
1858*5e7646d2SAndroid Build Coastguard Worker free(sspi->writeBuffer);
1859*5e7646d2SAndroid Build Coastguard Worker
1860*5e7646d2SAndroid Build Coastguard Worker if (sspi->localCert)
1861*5e7646d2SAndroid Build Coastguard Worker CertFreeCertificateContext(sspi->localCert);
1862*5e7646d2SAndroid Build Coastguard Worker
1863*5e7646d2SAndroid Build Coastguard Worker if (sspi->remoteCert)
1864*5e7646d2SAndroid Build Coastguard Worker CertFreeCertificateContext(sspi->remoteCert);
1865*5e7646d2SAndroid Build Coastguard Worker
1866*5e7646d2SAndroid Build Coastguard Worker free(sspi);
1867*5e7646d2SAndroid Build Coastguard Worker }
1868*5e7646d2SAndroid Build Coastguard Worker
1869*5e7646d2SAndroid Build Coastguard Worker
1870*5e7646d2SAndroid Build Coastguard Worker /*
1871*5e7646d2SAndroid Build Coastguard Worker * 'http_sspi_make_credentials()' - Create a TLS certificate in the system store.
1872*5e7646d2SAndroid Build Coastguard Worker */
1873*5e7646d2SAndroid Build Coastguard Worker
1874*5e7646d2SAndroid Build Coastguard Worker static BOOL /* O - 1 on success, 0 on failure */
http_sspi_make_credentials(_http_sspi_t * sspi,const LPWSTR container,const char * common_name,_http_mode_t mode,int years)1875*5e7646d2SAndroid Build Coastguard Worker http_sspi_make_credentials(
1876*5e7646d2SAndroid Build Coastguard Worker _http_sspi_t *sspi, /* I - SSPI data */
1877*5e7646d2SAndroid Build Coastguard Worker const LPWSTR container, /* I - Cert container name */
1878*5e7646d2SAndroid Build Coastguard Worker const char *common_name, /* I - Common name of certificate */
1879*5e7646d2SAndroid Build Coastguard Worker _http_mode_t mode, /* I - Client or server? */
1880*5e7646d2SAndroid Build Coastguard Worker int years) /* I - Years until expiration */
1881*5e7646d2SAndroid Build Coastguard Worker {
1882*5e7646d2SAndroid Build Coastguard Worker HCERTSTORE store = NULL; /* Certificate store */
1883*5e7646d2SAndroid Build Coastguard Worker PCCERT_CONTEXT storedContext = NULL; /* Context created from the store */
1884*5e7646d2SAndroid Build Coastguard Worker PCCERT_CONTEXT createdContext = NULL; /* Context created by us */
1885*5e7646d2SAndroid Build Coastguard Worker DWORD dwSize = 0; /* 32 bit size */
1886*5e7646d2SAndroid Build Coastguard Worker PBYTE p = NULL; /* Temporary storage */
1887*5e7646d2SAndroid Build Coastguard Worker HCRYPTPROV hProv = (HCRYPTPROV)NULL;
1888*5e7646d2SAndroid Build Coastguard Worker /* Handle to a CSP */
1889*5e7646d2SAndroid Build Coastguard Worker CERT_NAME_BLOB sib; /* Arbitrary array of bytes */
1890*5e7646d2SAndroid Build Coastguard Worker SCHANNEL_CRED SchannelCred; /* Schannel credential data */
1891*5e7646d2SAndroid Build Coastguard Worker TimeStamp tsExpiry; /* Time stamp */
1892*5e7646d2SAndroid Build Coastguard Worker SECURITY_STATUS Status; /* Status */
1893*5e7646d2SAndroid Build Coastguard Worker HCRYPTKEY hKey = (HCRYPTKEY)NULL; /* Handle to crypto key */
1894*5e7646d2SAndroid Build Coastguard Worker CRYPT_KEY_PROV_INFO kpi; /* Key container info */
1895*5e7646d2SAndroid Build Coastguard Worker SYSTEMTIME et; /* System time */
1896*5e7646d2SAndroid Build Coastguard Worker CERT_EXTENSIONS exts; /* Array of cert extensions */
1897*5e7646d2SAndroid Build Coastguard Worker CRYPT_KEY_PROV_INFO ckp; /* Handle to crypto key */
1898*5e7646d2SAndroid Build Coastguard Worker BOOL ok = TRUE; /* Return value */
1899*5e7646d2SAndroid Build Coastguard Worker
1900*5e7646d2SAndroid Build Coastguard Worker
1901*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4http_sspi_make_credentials(sspi=%p, container=%p, common_name=\"%s\", mode=%d, years=%d)", sspi, container, common_name, mode, years));
1902*5e7646d2SAndroid Build Coastguard Worker
1903*5e7646d2SAndroid Build Coastguard Worker if (!CryptAcquireContextW(&hProv, (LPWSTR)container, MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_MACHINE_KEYSET))
1904*5e7646d2SAndroid Build Coastguard Worker {
1905*5e7646d2SAndroid Build Coastguard Worker if (GetLastError() == NTE_EXISTS)
1906*5e7646d2SAndroid Build Coastguard Worker {
1907*5e7646d2SAndroid Build Coastguard Worker if (!CryptAcquireContextW(&hProv, (LPWSTR)container, MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET))
1908*5e7646d2SAndroid Build Coastguard Worker {
1909*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_make_credentials: CryptAcquireContext failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
1910*5e7646d2SAndroid Build Coastguard Worker ok = FALSE;
1911*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1912*5e7646d2SAndroid Build Coastguard Worker }
1913*5e7646d2SAndroid Build Coastguard Worker }
1914*5e7646d2SAndroid Build Coastguard Worker }
1915*5e7646d2SAndroid Build Coastguard Worker
1916*5e7646d2SAndroid Build Coastguard Worker store = CertOpenStore(CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING|PKCS_7_ASN_ENCODING, hProv, CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_NO_CRYPT_RELEASE_FLAG | CERT_STORE_OPEN_EXISTING_FLAG, L"MY");
1917*5e7646d2SAndroid Build Coastguard Worker
1918*5e7646d2SAndroid Build Coastguard Worker if (!store)
1919*5e7646d2SAndroid Build Coastguard Worker {
1920*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_make_credentials: CertOpenSystemStore failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
1921*5e7646d2SAndroid Build Coastguard Worker ok = FALSE;
1922*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1923*5e7646d2SAndroid Build Coastguard Worker }
1924*5e7646d2SAndroid Build Coastguard Worker
1925*5e7646d2SAndroid Build Coastguard Worker dwSize = 0;
1926*5e7646d2SAndroid Build Coastguard Worker
1927*5e7646d2SAndroid Build Coastguard Worker if (!CertStrToNameA(X509_ASN_ENCODING, common_name, CERT_OID_NAME_STR, NULL, NULL, &dwSize, NULL))
1928*5e7646d2SAndroid Build Coastguard Worker {
1929*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_make_credentials: CertStrToName failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
1930*5e7646d2SAndroid Build Coastguard Worker ok = FALSE;
1931*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1932*5e7646d2SAndroid Build Coastguard Worker }
1933*5e7646d2SAndroid Build Coastguard Worker
1934*5e7646d2SAndroid Build Coastguard Worker p = (PBYTE)malloc(dwSize);
1935*5e7646d2SAndroid Build Coastguard Worker
1936*5e7646d2SAndroid Build Coastguard Worker if (!p)
1937*5e7646d2SAndroid Build Coastguard Worker {
1938*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_make_credentials: malloc failed for %d bytes", dwSize));
1939*5e7646d2SAndroid Build Coastguard Worker ok = FALSE;
1940*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1941*5e7646d2SAndroid Build Coastguard Worker }
1942*5e7646d2SAndroid Build Coastguard Worker
1943*5e7646d2SAndroid Build Coastguard Worker if (!CertStrToNameA(X509_ASN_ENCODING, common_name, CERT_OID_NAME_STR, NULL, p, &dwSize, NULL))
1944*5e7646d2SAndroid Build Coastguard Worker {
1945*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_make_credentials: CertStrToName failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
1946*5e7646d2SAndroid Build Coastguard Worker ok = FALSE;
1947*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1948*5e7646d2SAndroid Build Coastguard Worker }
1949*5e7646d2SAndroid Build Coastguard Worker
1950*5e7646d2SAndroid Build Coastguard Worker /*
1951*5e7646d2SAndroid Build Coastguard Worker * Create a private key and self-signed certificate...
1952*5e7646d2SAndroid Build Coastguard Worker */
1953*5e7646d2SAndroid Build Coastguard Worker
1954*5e7646d2SAndroid Build Coastguard Worker if (!CryptGenKey(hProv, AT_KEYEXCHANGE, CRYPT_EXPORTABLE, &hKey))
1955*5e7646d2SAndroid Build Coastguard Worker {
1956*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_make_credentials: CryptGenKey failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
1957*5e7646d2SAndroid Build Coastguard Worker ok = FALSE;
1958*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1959*5e7646d2SAndroid Build Coastguard Worker }
1960*5e7646d2SAndroid Build Coastguard Worker
1961*5e7646d2SAndroid Build Coastguard Worker ZeroMemory(&kpi, sizeof(kpi));
1962*5e7646d2SAndroid Build Coastguard Worker kpi.pwszContainerName = (LPWSTR)container;
1963*5e7646d2SAndroid Build Coastguard Worker kpi.pwszProvName = MS_DEF_PROV_W;
1964*5e7646d2SAndroid Build Coastguard Worker kpi.dwProvType = PROV_RSA_FULL;
1965*5e7646d2SAndroid Build Coastguard Worker kpi.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
1966*5e7646d2SAndroid Build Coastguard Worker kpi.dwKeySpec = AT_KEYEXCHANGE;
1967*5e7646d2SAndroid Build Coastguard Worker
1968*5e7646d2SAndroid Build Coastguard Worker GetSystemTime(&et);
1969*5e7646d2SAndroid Build Coastguard Worker et.wYear += years;
1970*5e7646d2SAndroid Build Coastguard Worker if (et.wMonth == 2 && et.wDay == 29)
1971*5e7646d2SAndroid Build Coastguard Worker et.wDay = 28; /* Avoid Feb 29th due to leap years */
1972*5e7646d2SAndroid Build Coastguard Worker
1973*5e7646d2SAndroid Build Coastguard Worker ZeroMemory(&exts, sizeof(exts));
1974*5e7646d2SAndroid Build Coastguard Worker
1975*5e7646d2SAndroid Build Coastguard Worker createdContext = CertCreateSelfSignCertificate(hProv, &sib, 0, &kpi, NULL, NULL, &et, &exts);
1976*5e7646d2SAndroid Build Coastguard Worker
1977*5e7646d2SAndroid Build Coastguard Worker if (!createdContext)
1978*5e7646d2SAndroid Build Coastguard Worker {
1979*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_make_credentials: CertCreateSelfSignCertificate failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
1980*5e7646d2SAndroid Build Coastguard Worker ok = FALSE;
1981*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1982*5e7646d2SAndroid Build Coastguard Worker }
1983*5e7646d2SAndroid Build Coastguard Worker
1984*5e7646d2SAndroid Build Coastguard Worker /*
1985*5e7646d2SAndroid Build Coastguard Worker * Add the created context to the named store, and associate it with the named
1986*5e7646d2SAndroid Build Coastguard Worker * container...
1987*5e7646d2SAndroid Build Coastguard Worker */
1988*5e7646d2SAndroid Build Coastguard Worker
1989*5e7646d2SAndroid Build Coastguard Worker if (!CertAddCertificateContextToStore(store, createdContext, CERT_STORE_ADD_REPLACE_EXISTING, &storedContext))
1990*5e7646d2SAndroid Build Coastguard Worker {
1991*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_make_credentials: CertAddCertificateContextToStore failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
1992*5e7646d2SAndroid Build Coastguard Worker ok = FALSE;
1993*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1994*5e7646d2SAndroid Build Coastguard Worker }
1995*5e7646d2SAndroid Build Coastguard Worker
1996*5e7646d2SAndroid Build Coastguard Worker ZeroMemory(&ckp, sizeof(ckp));
1997*5e7646d2SAndroid Build Coastguard Worker ckp.pwszContainerName = (LPWSTR) container;
1998*5e7646d2SAndroid Build Coastguard Worker ckp.pwszProvName = MS_DEF_PROV_W;
1999*5e7646d2SAndroid Build Coastguard Worker ckp.dwProvType = PROV_RSA_FULL;
2000*5e7646d2SAndroid Build Coastguard Worker ckp.dwFlags = CRYPT_MACHINE_KEYSET;
2001*5e7646d2SAndroid Build Coastguard Worker ckp.dwKeySpec = AT_KEYEXCHANGE;
2002*5e7646d2SAndroid Build Coastguard Worker
2003*5e7646d2SAndroid Build Coastguard Worker if (!CertSetCertificateContextProperty(storedContext, CERT_KEY_PROV_INFO_PROP_ID, 0, &ckp))
2004*5e7646d2SAndroid Build Coastguard Worker {
2005*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_make_credentials: CertSetCertificateContextProperty failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), GetLastError())));
2006*5e7646d2SAndroid Build Coastguard Worker ok = FALSE;
2007*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
2008*5e7646d2SAndroid Build Coastguard Worker }
2009*5e7646d2SAndroid Build Coastguard Worker
2010*5e7646d2SAndroid Build Coastguard Worker /*
2011*5e7646d2SAndroid Build Coastguard Worker * Get a handle to use the certificate...
2012*5e7646d2SAndroid Build Coastguard Worker */
2013*5e7646d2SAndroid Build Coastguard Worker
2014*5e7646d2SAndroid Build Coastguard Worker ZeroMemory(&SchannelCred, sizeof(SchannelCred));
2015*5e7646d2SAndroid Build Coastguard Worker
2016*5e7646d2SAndroid Build Coastguard Worker SchannelCred.dwVersion = SCHANNEL_CRED_VERSION;
2017*5e7646d2SAndroid Build Coastguard Worker SchannelCred.cCreds = 1;
2018*5e7646d2SAndroid Build Coastguard Worker SchannelCred.paCred = &storedContext;
2019*5e7646d2SAndroid Build Coastguard Worker
2020*5e7646d2SAndroid Build Coastguard Worker /*
2021*5e7646d2SAndroid Build Coastguard Worker * Create an SSPI credential.
2022*5e7646d2SAndroid Build Coastguard Worker */
2023*5e7646d2SAndroid Build Coastguard Worker
2024*5e7646d2SAndroid Build Coastguard Worker Status = AcquireCredentialsHandle(NULL, UNISP_NAME, mode == _HTTP_MODE_SERVER ? SECPKG_CRED_INBOUND : SECPKG_CRED_OUTBOUND, NULL, &SchannelCred, NULL, NULL, &sspi->creds, &tsExpiry);
2025*5e7646d2SAndroid Build Coastguard Worker if (Status != SEC_E_OK)
2026*5e7646d2SAndroid Build Coastguard Worker {
2027*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_make_credentials: AcquireCredentialsHandle failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), Status)));
2028*5e7646d2SAndroid Build Coastguard Worker ok = FALSE;
2029*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
2030*5e7646d2SAndroid Build Coastguard Worker }
2031*5e7646d2SAndroid Build Coastguard Worker
2032*5e7646d2SAndroid Build Coastguard Worker cleanup:
2033*5e7646d2SAndroid Build Coastguard Worker
2034*5e7646d2SAndroid Build Coastguard Worker /*
2035*5e7646d2SAndroid Build Coastguard Worker * Cleanup
2036*5e7646d2SAndroid Build Coastguard Worker */
2037*5e7646d2SAndroid Build Coastguard Worker
2038*5e7646d2SAndroid Build Coastguard Worker if (hKey)
2039*5e7646d2SAndroid Build Coastguard Worker CryptDestroyKey(hKey);
2040*5e7646d2SAndroid Build Coastguard Worker
2041*5e7646d2SAndroid Build Coastguard Worker if (createdContext)
2042*5e7646d2SAndroid Build Coastguard Worker CertFreeCertificateContext(createdContext);
2043*5e7646d2SAndroid Build Coastguard Worker
2044*5e7646d2SAndroid Build Coastguard Worker if (storedContext)
2045*5e7646d2SAndroid Build Coastguard Worker CertFreeCertificateContext(storedContext);
2046*5e7646d2SAndroid Build Coastguard Worker
2047*5e7646d2SAndroid Build Coastguard Worker if (p)
2048*5e7646d2SAndroid Build Coastguard Worker free(p);
2049*5e7646d2SAndroid Build Coastguard Worker
2050*5e7646d2SAndroid Build Coastguard Worker if (store)
2051*5e7646d2SAndroid Build Coastguard Worker CertCloseStore(store, 0);
2052*5e7646d2SAndroid Build Coastguard Worker
2053*5e7646d2SAndroid Build Coastguard Worker if (hProv)
2054*5e7646d2SAndroid Build Coastguard Worker CryptReleaseContext(hProv, 0);
2055*5e7646d2SAndroid Build Coastguard Worker
2056*5e7646d2SAndroid Build Coastguard Worker return (ok);
2057*5e7646d2SAndroid Build Coastguard Worker }
2058*5e7646d2SAndroid Build Coastguard Worker
2059*5e7646d2SAndroid Build Coastguard Worker
2060*5e7646d2SAndroid Build Coastguard Worker /*
2061*5e7646d2SAndroid Build Coastguard Worker * 'http_sspi_server()' - Negotiate a TLS connection as a server.
2062*5e7646d2SAndroid Build Coastguard Worker */
2063*5e7646d2SAndroid Build Coastguard Worker
2064*5e7646d2SAndroid Build Coastguard Worker static int /* O - 0 on success, -1 on failure */
http_sspi_server(http_t * http,const char * hostname)2065*5e7646d2SAndroid Build Coastguard Worker http_sspi_server(http_t *http, /* I - HTTP connection */
2066*5e7646d2SAndroid Build Coastguard Worker const char *hostname) /* I - Hostname of server */
2067*5e7646d2SAndroid Build Coastguard Worker {
2068*5e7646d2SAndroid Build Coastguard Worker _http_sspi_t *sspi = http->tls; /* I - SSPI data */
2069*5e7646d2SAndroid Build Coastguard Worker char common_name[512]; /* Common name for cert */
2070*5e7646d2SAndroid Build Coastguard Worker DWORD dwSSPIFlags; /* SSL connection attributes we want */
2071*5e7646d2SAndroid Build Coastguard Worker DWORD dwSSPIOutFlags; /* SSL connection attributes we got */
2072*5e7646d2SAndroid Build Coastguard Worker TimeStamp tsExpiry; /* Time stamp */
2073*5e7646d2SAndroid Build Coastguard Worker SECURITY_STATUS scRet; /* SSPI Status */
2074*5e7646d2SAndroid Build Coastguard Worker SecBufferDesc inBuffer; /* Array of SecBuffer structs */
2075*5e7646d2SAndroid Build Coastguard Worker SecBuffer inBuffers[2]; /* Security package buffer */
2076*5e7646d2SAndroid Build Coastguard Worker SecBufferDesc outBuffer; /* Array of SecBuffer structs */
2077*5e7646d2SAndroid Build Coastguard Worker SecBuffer outBuffers[1]; /* Security package buffer */
2078*5e7646d2SAndroid Build Coastguard Worker int num = 0; /* 32 bit status value */
2079*5e7646d2SAndroid Build Coastguard Worker BOOL fInitContext = TRUE; /* Has the context been init'd? */
2080*5e7646d2SAndroid Build Coastguard Worker int ret = 0; /* Return value */
2081*5e7646d2SAndroid Build Coastguard Worker
2082*5e7646d2SAndroid Build Coastguard Worker
2083*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4http_sspi_server(http=%p, hostname=\"%s\")", http, hostname));
2084*5e7646d2SAndroid Build Coastguard Worker
2085*5e7646d2SAndroid Build Coastguard Worker dwSSPIFlags = ASC_REQ_SEQUENCE_DETECT |
2086*5e7646d2SAndroid Build Coastguard Worker ASC_REQ_REPLAY_DETECT |
2087*5e7646d2SAndroid Build Coastguard Worker ASC_REQ_CONFIDENTIALITY |
2088*5e7646d2SAndroid Build Coastguard Worker ASC_REQ_EXTENDED_ERROR |
2089*5e7646d2SAndroid Build Coastguard Worker ASC_REQ_ALLOCATE_MEMORY |
2090*5e7646d2SAndroid Build Coastguard Worker ASC_REQ_STREAM;
2091*5e7646d2SAndroid Build Coastguard Worker
2092*5e7646d2SAndroid Build Coastguard Worker sspi->decryptBufferUsed = 0;
2093*5e7646d2SAndroid Build Coastguard Worker
2094*5e7646d2SAndroid Build Coastguard Worker /*
2095*5e7646d2SAndroid Build Coastguard Worker * Lookup the server certificate...
2096*5e7646d2SAndroid Build Coastguard Worker */
2097*5e7646d2SAndroid Build Coastguard Worker
2098*5e7646d2SAndroid Build Coastguard Worker snprintf(common_name, sizeof(common_name), "CN=%s", hostname);
2099*5e7646d2SAndroid Build Coastguard Worker
2100*5e7646d2SAndroid Build Coastguard Worker if (!http_sspi_find_credentials(http, L"ServerContainer", common_name))
2101*5e7646d2SAndroid Build Coastguard Worker if (!http_sspi_make_credentials(http->tls, L"ServerContainer", common_name, _HTTP_MODE_SERVER, 10))
2102*5e7646d2SAndroid Build Coastguard Worker {
2103*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5http_sspi_server: Unable to get server credentials.");
2104*5e7646d2SAndroid Build Coastguard Worker return (-1);
2105*5e7646d2SAndroid Build Coastguard Worker }
2106*5e7646d2SAndroid Build Coastguard Worker
2107*5e7646d2SAndroid Build Coastguard Worker /*
2108*5e7646d2SAndroid Build Coastguard Worker * Set OutBuffer for AcceptSecurityContext call
2109*5e7646d2SAndroid Build Coastguard Worker */
2110*5e7646d2SAndroid Build Coastguard Worker
2111*5e7646d2SAndroid Build Coastguard Worker outBuffer.cBuffers = 1;
2112*5e7646d2SAndroid Build Coastguard Worker outBuffer.pBuffers = outBuffers;
2113*5e7646d2SAndroid Build Coastguard Worker outBuffer.ulVersion = SECBUFFER_VERSION;
2114*5e7646d2SAndroid Build Coastguard Worker
2115*5e7646d2SAndroid Build Coastguard Worker scRet = SEC_I_CONTINUE_NEEDED;
2116*5e7646d2SAndroid Build Coastguard Worker
2117*5e7646d2SAndroid Build Coastguard Worker while (scRet == SEC_I_CONTINUE_NEEDED ||
2118*5e7646d2SAndroid Build Coastguard Worker scRet == SEC_E_INCOMPLETE_MESSAGE ||
2119*5e7646d2SAndroid Build Coastguard Worker scRet == SEC_I_INCOMPLETE_CREDENTIALS)
2120*5e7646d2SAndroid Build Coastguard Worker {
2121*5e7646d2SAndroid Build Coastguard Worker if (sspi->decryptBufferUsed == 0 || scRet == SEC_E_INCOMPLETE_MESSAGE)
2122*5e7646d2SAndroid Build Coastguard Worker {
2123*5e7646d2SAndroid Build Coastguard Worker if (sspi->decryptBufferLength <= sspi->decryptBufferUsed)
2124*5e7646d2SAndroid Build Coastguard Worker {
2125*5e7646d2SAndroid Build Coastguard Worker BYTE *temp; /* New buffer */
2126*5e7646d2SAndroid Build Coastguard Worker
2127*5e7646d2SAndroid Build Coastguard Worker if (sspi->decryptBufferLength >= 262144)
2128*5e7646d2SAndroid Build Coastguard Worker {
2129*5e7646d2SAndroid Build Coastguard Worker WSASetLastError(E_OUTOFMEMORY);
2130*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5http_sspi_server: Decryption buffer too large (>256k)");
2131*5e7646d2SAndroid Build Coastguard Worker return (-1);
2132*5e7646d2SAndroid Build Coastguard Worker }
2133*5e7646d2SAndroid Build Coastguard Worker
2134*5e7646d2SAndroid Build Coastguard Worker if ((temp = realloc(sspi->decryptBuffer, sspi->decryptBufferLength + 4096)) == NULL)
2135*5e7646d2SAndroid Build Coastguard Worker {
2136*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_server: Unable to allocate %d byte buffer.", sspi->decryptBufferLength + 4096));
2137*5e7646d2SAndroid Build Coastguard Worker WSASetLastError(E_OUTOFMEMORY);
2138*5e7646d2SAndroid Build Coastguard Worker return (-1);
2139*5e7646d2SAndroid Build Coastguard Worker }
2140*5e7646d2SAndroid Build Coastguard Worker
2141*5e7646d2SAndroid Build Coastguard Worker sspi->decryptBufferLength += 4096;
2142*5e7646d2SAndroid Build Coastguard Worker sspi->decryptBuffer = temp;
2143*5e7646d2SAndroid Build Coastguard Worker }
2144*5e7646d2SAndroid Build Coastguard Worker
2145*5e7646d2SAndroid Build Coastguard Worker for (;;)
2146*5e7646d2SAndroid Build Coastguard Worker {
2147*5e7646d2SAndroid Build Coastguard Worker num = recv(http->fd, sspi->decryptBuffer + sspi->decryptBufferUsed, (int)(sspi->decryptBufferLength - sspi->decryptBufferUsed), 0);
2148*5e7646d2SAndroid Build Coastguard Worker
2149*5e7646d2SAndroid Build Coastguard Worker if (num == -1 && WSAGetLastError() == WSAEWOULDBLOCK)
2150*5e7646d2SAndroid Build Coastguard Worker Sleep(1);
2151*5e7646d2SAndroid Build Coastguard Worker else
2152*5e7646d2SAndroid Build Coastguard Worker break;
2153*5e7646d2SAndroid Build Coastguard Worker }
2154*5e7646d2SAndroid Build Coastguard Worker
2155*5e7646d2SAndroid Build Coastguard Worker if (num < 0)
2156*5e7646d2SAndroid Build Coastguard Worker {
2157*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_server: recv failed: %d", WSAGetLastError()));
2158*5e7646d2SAndroid Build Coastguard Worker return (-1);
2159*5e7646d2SAndroid Build Coastguard Worker }
2160*5e7646d2SAndroid Build Coastguard Worker else if (num == 0)
2161*5e7646d2SAndroid Build Coastguard Worker {
2162*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5http_sspi_server: client disconnected");
2163*5e7646d2SAndroid Build Coastguard Worker return (-1);
2164*5e7646d2SAndroid Build Coastguard Worker }
2165*5e7646d2SAndroid Build Coastguard Worker
2166*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_server: received %d (handshake) bytes from client.", num));
2167*5e7646d2SAndroid Build Coastguard Worker sspi->decryptBufferUsed += num;
2168*5e7646d2SAndroid Build Coastguard Worker }
2169*5e7646d2SAndroid Build Coastguard Worker
2170*5e7646d2SAndroid Build Coastguard Worker /*
2171*5e7646d2SAndroid Build Coastguard Worker * InBuffers[1] is for getting extra data that SSPI/SCHANNEL doesn't process
2172*5e7646d2SAndroid Build Coastguard Worker * on this run around the loop.
2173*5e7646d2SAndroid Build Coastguard Worker */
2174*5e7646d2SAndroid Build Coastguard Worker
2175*5e7646d2SAndroid Build Coastguard Worker inBuffers[0].pvBuffer = sspi->decryptBuffer;
2176*5e7646d2SAndroid Build Coastguard Worker inBuffers[0].cbBuffer = (unsigned long)sspi->decryptBufferUsed;
2177*5e7646d2SAndroid Build Coastguard Worker inBuffers[0].BufferType = SECBUFFER_TOKEN;
2178*5e7646d2SAndroid Build Coastguard Worker
2179*5e7646d2SAndroid Build Coastguard Worker inBuffers[1].pvBuffer = NULL;
2180*5e7646d2SAndroid Build Coastguard Worker inBuffers[1].cbBuffer = 0;
2181*5e7646d2SAndroid Build Coastguard Worker inBuffers[1].BufferType = SECBUFFER_EMPTY;
2182*5e7646d2SAndroid Build Coastguard Worker
2183*5e7646d2SAndroid Build Coastguard Worker inBuffer.cBuffers = 2;
2184*5e7646d2SAndroid Build Coastguard Worker inBuffer.pBuffers = inBuffers;
2185*5e7646d2SAndroid Build Coastguard Worker inBuffer.ulVersion = SECBUFFER_VERSION;
2186*5e7646d2SAndroid Build Coastguard Worker
2187*5e7646d2SAndroid Build Coastguard Worker /*
2188*5e7646d2SAndroid Build Coastguard Worker * Initialize these so if we fail, pvBuffer contains NULL, so we don't try to
2189*5e7646d2SAndroid Build Coastguard Worker * free random garbage at the quit.
2190*5e7646d2SAndroid Build Coastguard Worker */
2191*5e7646d2SAndroid Build Coastguard Worker
2192*5e7646d2SAndroid Build Coastguard Worker outBuffers[0].pvBuffer = NULL;
2193*5e7646d2SAndroid Build Coastguard Worker outBuffers[0].BufferType = SECBUFFER_TOKEN;
2194*5e7646d2SAndroid Build Coastguard Worker outBuffers[0].cbBuffer = 0;
2195*5e7646d2SAndroid Build Coastguard Worker
2196*5e7646d2SAndroid Build Coastguard Worker scRet = AcceptSecurityContext(&sspi->creds, (fInitContext?NULL:&sspi->context), &inBuffer, dwSSPIFlags, SECURITY_NATIVE_DREP, (fInitContext?&sspi->context:NULL), &outBuffer, &dwSSPIOutFlags, &tsExpiry);
2197*5e7646d2SAndroid Build Coastguard Worker
2198*5e7646d2SAndroid Build Coastguard Worker fInitContext = FALSE;
2199*5e7646d2SAndroid Build Coastguard Worker
2200*5e7646d2SAndroid Build Coastguard Worker if (scRet == SEC_E_OK ||
2201*5e7646d2SAndroid Build Coastguard Worker scRet == SEC_I_CONTINUE_NEEDED ||
2202*5e7646d2SAndroid Build Coastguard Worker (FAILED(scRet) && ((dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR) != 0)))
2203*5e7646d2SAndroid Build Coastguard Worker {
2204*5e7646d2SAndroid Build Coastguard Worker if (outBuffers[0].cbBuffer && outBuffers[0].pvBuffer)
2205*5e7646d2SAndroid Build Coastguard Worker {
2206*5e7646d2SAndroid Build Coastguard Worker /*
2207*5e7646d2SAndroid Build Coastguard Worker * Send response to server if there is one.
2208*5e7646d2SAndroid Build Coastguard Worker */
2209*5e7646d2SAndroid Build Coastguard Worker
2210*5e7646d2SAndroid Build Coastguard Worker num = send(http->fd, outBuffers[0].pvBuffer, outBuffers[0].cbBuffer, 0);
2211*5e7646d2SAndroid Build Coastguard Worker
2212*5e7646d2SAndroid Build Coastguard Worker if (num <= 0)
2213*5e7646d2SAndroid Build Coastguard Worker {
2214*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_server: handshake send failed: %d", WSAGetLastError()));
2215*5e7646d2SAndroid Build Coastguard Worker return (-1);
2216*5e7646d2SAndroid Build Coastguard Worker }
2217*5e7646d2SAndroid Build Coastguard Worker
2218*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_server: sent %d handshake bytes to client.", outBuffers[0].cbBuffer));
2219*5e7646d2SAndroid Build Coastguard Worker
2220*5e7646d2SAndroid Build Coastguard Worker FreeContextBuffer(outBuffers[0].pvBuffer);
2221*5e7646d2SAndroid Build Coastguard Worker outBuffers[0].pvBuffer = NULL;
2222*5e7646d2SAndroid Build Coastguard Worker }
2223*5e7646d2SAndroid Build Coastguard Worker }
2224*5e7646d2SAndroid Build Coastguard Worker
2225*5e7646d2SAndroid Build Coastguard Worker if (scRet == SEC_E_OK)
2226*5e7646d2SAndroid Build Coastguard Worker {
2227*5e7646d2SAndroid Build Coastguard Worker /*
2228*5e7646d2SAndroid Build Coastguard Worker * If there's extra data then save it for next time we go to decrypt.
2229*5e7646d2SAndroid Build Coastguard Worker */
2230*5e7646d2SAndroid Build Coastguard Worker
2231*5e7646d2SAndroid Build Coastguard Worker if (inBuffers[1].BufferType == SECBUFFER_EXTRA)
2232*5e7646d2SAndroid Build Coastguard Worker {
2233*5e7646d2SAndroid Build Coastguard Worker memcpy(sspi->decryptBuffer, (LPBYTE)(sspi->decryptBuffer + sspi->decryptBufferUsed - inBuffers[1].cbBuffer), inBuffers[1].cbBuffer);
2234*5e7646d2SAndroid Build Coastguard Worker sspi->decryptBufferUsed = inBuffers[1].cbBuffer;
2235*5e7646d2SAndroid Build Coastguard Worker }
2236*5e7646d2SAndroid Build Coastguard Worker else
2237*5e7646d2SAndroid Build Coastguard Worker {
2238*5e7646d2SAndroid Build Coastguard Worker sspi->decryptBufferUsed = 0;
2239*5e7646d2SAndroid Build Coastguard Worker }
2240*5e7646d2SAndroid Build Coastguard Worker break;
2241*5e7646d2SAndroid Build Coastguard Worker }
2242*5e7646d2SAndroid Build Coastguard Worker else if (FAILED(scRet) && scRet != SEC_E_INCOMPLETE_MESSAGE)
2243*5e7646d2SAndroid Build Coastguard Worker {
2244*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_server: AcceptSecurityContext failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), scRet)));
2245*5e7646d2SAndroid Build Coastguard Worker ret = -1;
2246*5e7646d2SAndroid Build Coastguard Worker break;
2247*5e7646d2SAndroid Build Coastguard Worker }
2248*5e7646d2SAndroid Build Coastguard Worker
2249*5e7646d2SAndroid Build Coastguard Worker if (scRet != SEC_E_INCOMPLETE_MESSAGE &&
2250*5e7646d2SAndroid Build Coastguard Worker scRet != SEC_I_INCOMPLETE_CREDENTIALS)
2251*5e7646d2SAndroid Build Coastguard Worker {
2252*5e7646d2SAndroid Build Coastguard Worker if (inBuffers[1].BufferType == SECBUFFER_EXTRA)
2253*5e7646d2SAndroid Build Coastguard Worker {
2254*5e7646d2SAndroid Build Coastguard Worker memcpy(sspi->decryptBuffer, (LPBYTE)(sspi->decryptBuffer + sspi->decryptBufferUsed - inBuffers[1].cbBuffer), inBuffers[1].cbBuffer);
2255*5e7646d2SAndroid Build Coastguard Worker sspi->decryptBufferUsed = inBuffers[1].cbBuffer;
2256*5e7646d2SAndroid Build Coastguard Worker }
2257*5e7646d2SAndroid Build Coastguard Worker else
2258*5e7646d2SAndroid Build Coastguard Worker {
2259*5e7646d2SAndroid Build Coastguard Worker sspi->decryptBufferUsed = 0;
2260*5e7646d2SAndroid Build Coastguard Worker }
2261*5e7646d2SAndroid Build Coastguard Worker }
2262*5e7646d2SAndroid Build Coastguard Worker }
2263*5e7646d2SAndroid Build Coastguard Worker
2264*5e7646d2SAndroid Build Coastguard Worker if (!ret)
2265*5e7646d2SAndroid Build Coastguard Worker {
2266*5e7646d2SAndroid Build Coastguard Worker sspi->contextInitialized = TRUE;
2267*5e7646d2SAndroid Build Coastguard Worker
2268*5e7646d2SAndroid Build Coastguard Worker /*
2269*5e7646d2SAndroid Build Coastguard Worker * Find out how big the header will be:
2270*5e7646d2SAndroid Build Coastguard Worker */
2271*5e7646d2SAndroid Build Coastguard Worker
2272*5e7646d2SAndroid Build Coastguard Worker scRet = QueryContextAttributes(&sspi->context, SECPKG_ATTR_STREAM_SIZES, &sspi->streamSizes);
2273*5e7646d2SAndroid Build Coastguard Worker
2274*5e7646d2SAndroid Build Coastguard Worker if (scRet != SEC_E_OK)
2275*5e7646d2SAndroid Build Coastguard Worker {
2276*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5http_sspi_server: QueryContextAttributes failed: %s", http_sspi_strerror(sspi->error, sizeof(sspi->error), scRet)));
2277*5e7646d2SAndroid Build Coastguard Worker ret = -1;
2278*5e7646d2SAndroid Build Coastguard Worker }
2279*5e7646d2SAndroid Build Coastguard Worker }
2280*5e7646d2SAndroid Build Coastguard Worker
2281*5e7646d2SAndroid Build Coastguard Worker return (ret);
2282*5e7646d2SAndroid Build Coastguard Worker }
2283*5e7646d2SAndroid Build Coastguard Worker
2284*5e7646d2SAndroid Build Coastguard Worker
2285*5e7646d2SAndroid Build Coastguard Worker /*
2286*5e7646d2SAndroid Build Coastguard Worker * 'http_sspi_strerror()' - Return a string for the specified error code.
2287*5e7646d2SAndroid Build Coastguard Worker */
2288*5e7646d2SAndroid Build Coastguard Worker
2289*5e7646d2SAndroid Build Coastguard Worker static const char * /* O - String for error */
http_sspi_strerror(char * buffer,size_t bufsize,DWORD code)2290*5e7646d2SAndroid Build Coastguard Worker http_sspi_strerror(char *buffer, /* I - Error message buffer */
2291*5e7646d2SAndroid Build Coastguard Worker size_t bufsize, /* I - Size of buffer */
2292*5e7646d2SAndroid Build Coastguard Worker DWORD code) /* I - Error code */
2293*5e7646d2SAndroid Build Coastguard Worker {
2294*5e7646d2SAndroid Build Coastguard Worker if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, code, 0, buffer, bufsize, NULL))
2295*5e7646d2SAndroid Build Coastguard Worker {
2296*5e7646d2SAndroid Build Coastguard Worker /*
2297*5e7646d2SAndroid Build Coastguard Worker * Strip trailing CR + LF...
2298*5e7646d2SAndroid Build Coastguard Worker */
2299*5e7646d2SAndroid Build Coastguard Worker
2300*5e7646d2SAndroid Build Coastguard Worker char *ptr; /* Pointer into error message */
2301*5e7646d2SAndroid Build Coastguard Worker
2302*5e7646d2SAndroid Build Coastguard Worker for (ptr = buffer + strlen(buffer) - 1; ptr >= buffer; ptr --)
2303*5e7646d2SAndroid Build Coastguard Worker if (*ptr == '\n' || *ptr == '\r')
2304*5e7646d2SAndroid Build Coastguard Worker *ptr = '\0';
2305*5e7646d2SAndroid Build Coastguard Worker else
2306*5e7646d2SAndroid Build Coastguard Worker break;
2307*5e7646d2SAndroid Build Coastguard Worker }
2308*5e7646d2SAndroid Build Coastguard Worker else
2309*5e7646d2SAndroid Build Coastguard Worker snprintf(buffer, bufsize, "Unknown error %x", code);
2310*5e7646d2SAndroid Build Coastguard Worker
2311*5e7646d2SAndroid Build Coastguard Worker return (buffer);
2312*5e7646d2SAndroid Build Coastguard Worker }
2313*5e7646d2SAndroid Build Coastguard Worker
2314*5e7646d2SAndroid Build Coastguard Worker
2315*5e7646d2SAndroid Build Coastguard Worker /*
2316*5e7646d2SAndroid Build Coastguard Worker * 'http_sspi_verify()' - Verify a certificate.
2317*5e7646d2SAndroid Build Coastguard Worker */
2318*5e7646d2SAndroid Build Coastguard Worker
2319*5e7646d2SAndroid Build Coastguard Worker static DWORD /* O - Error code (0 == No error) */
http_sspi_verify(PCCERT_CONTEXT cert,const char * common_name,DWORD dwCertFlags)2320*5e7646d2SAndroid Build Coastguard Worker http_sspi_verify(
2321*5e7646d2SAndroid Build Coastguard Worker PCCERT_CONTEXT cert, /* I - Server certificate */
2322*5e7646d2SAndroid Build Coastguard Worker const char *common_name, /* I - Common name */
2323*5e7646d2SAndroid Build Coastguard Worker DWORD dwCertFlags) /* I - Verification flags */
2324*5e7646d2SAndroid Build Coastguard Worker {
2325*5e7646d2SAndroid Build Coastguard Worker HTTPSPolicyCallbackData httpsPolicy; /* HTTPS Policy Struct */
2326*5e7646d2SAndroid Build Coastguard Worker CERT_CHAIN_POLICY_PARA policyPara; /* Cert chain policy parameters */
2327*5e7646d2SAndroid Build Coastguard Worker CERT_CHAIN_POLICY_STATUS policyStatus;/* Cert chain policy status */
2328*5e7646d2SAndroid Build Coastguard Worker CERT_CHAIN_PARA chainPara; /* Used for searching and matching criteria */
2329*5e7646d2SAndroid Build Coastguard Worker PCCERT_CHAIN_CONTEXT chainContext = NULL;
2330*5e7646d2SAndroid Build Coastguard Worker /* Certificate chain */
2331*5e7646d2SAndroid Build Coastguard Worker PWSTR commonNameUnicode = NULL;
2332*5e7646d2SAndroid Build Coastguard Worker /* Unicode common name */
2333*5e7646d2SAndroid Build Coastguard Worker LPSTR rgszUsages[] = { szOID_PKIX_KP_SERVER_AUTH,
2334*5e7646d2SAndroid Build Coastguard Worker szOID_SERVER_GATED_CRYPTO,
2335*5e7646d2SAndroid Build Coastguard Worker szOID_SGC_NETSCAPE };
2336*5e7646d2SAndroid Build Coastguard Worker /* How are we using this certificate? */
2337*5e7646d2SAndroid Build Coastguard Worker DWORD cUsages = sizeof(rgszUsages) / sizeof(LPSTR);
2338*5e7646d2SAndroid Build Coastguard Worker /* Number of ites in rgszUsages */
2339*5e7646d2SAndroid Build Coastguard Worker DWORD count; /* 32 bit count variable */
2340*5e7646d2SAndroid Build Coastguard Worker DWORD status; /* Return value */
2341*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
2342*5e7646d2SAndroid Build Coastguard Worker char error[1024]; /* Error message string */
2343*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
2344*5e7646d2SAndroid Build Coastguard Worker
2345*5e7646d2SAndroid Build Coastguard Worker
2346*5e7646d2SAndroid Build Coastguard Worker if (!cert)
2347*5e7646d2SAndroid Build Coastguard Worker return (SEC_E_WRONG_PRINCIPAL);
2348*5e7646d2SAndroid Build Coastguard Worker
2349*5e7646d2SAndroid Build Coastguard Worker /*
2350*5e7646d2SAndroid Build Coastguard Worker * Convert common name to Unicode.
2351*5e7646d2SAndroid Build Coastguard Worker */
2352*5e7646d2SAndroid Build Coastguard Worker
2353*5e7646d2SAndroid Build Coastguard Worker if (!common_name || !*common_name)
2354*5e7646d2SAndroid Build Coastguard Worker return (SEC_E_WRONG_PRINCIPAL);
2355*5e7646d2SAndroid Build Coastguard Worker
2356*5e7646d2SAndroid Build Coastguard Worker count = MultiByteToWideChar(CP_ACP, 0, common_name, -1, NULL, 0);
2357*5e7646d2SAndroid Build Coastguard Worker commonNameUnicode = LocalAlloc(LMEM_FIXED, count * sizeof(WCHAR));
2358*5e7646d2SAndroid Build Coastguard Worker if (!commonNameUnicode)
2359*5e7646d2SAndroid Build Coastguard Worker return (SEC_E_INSUFFICIENT_MEMORY);
2360*5e7646d2SAndroid Build Coastguard Worker
2361*5e7646d2SAndroid Build Coastguard Worker if (!MultiByteToWideChar(CP_ACP, 0, common_name, -1, commonNameUnicode, count))
2362*5e7646d2SAndroid Build Coastguard Worker {
2363*5e7646d2SAndroid Build Coastguard Worker LocalFree(commonNameUnicode);
2364*5e7646d2SAndroid Build Coastguard Worker return (SEC_E_WRONG_PRINCIPAL);
2365*5e7646d2SAndroid Build Coastguard Worker }
2366*5e7646d2SAndroid Build Coastguard Worker
2367*5e7646d2SAndroid Build Coastguard Worker /*
2368*5e7646d2SAndroid Build Coastguard Worker * Build certificate chain.
2369*5e7646d2SAndroid Build Coastguard Worker */
2370*5e7646d2SAndroid Build Coastguard Worker
2371*5e7646d2SAndroid Build Coastguard Worker ZeroMemory(&chainPara, sizeof(chainPara));
2372*5e7646d2SAndroid Build Coastguard Worker
2373*5e7646d2SAndroid Build Coastguard Worker chainPara.cbSize = sizeof(chainPara);
2374*5e7646d2SAndroid Build Coastguard Worker chainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
2375*5e7646d2SAndroid Build Coastguard Worker chainPara.RequestedUsage.Usage.cUsageIdentifier = cUsages;
2376*5e7646d2SAndroid Build Coastguard Worker chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = rgszUsages;
2377*5e7646d2SAndroid Build Coastguard Worker
2378*5e7646d2SAndroid Build Coastguard Worker if (!CertGetCertificateChain(NULL, cert, NULL, cert->hCertStore, &chainPara, 0, NULL, &chainContext))
2379*5e7646d2SAndroid Build Coastguard Worker {
2380*5e7646d2SAndroid Build Coastguard Worker status = GetLastError();
2381*5e7646d2SAndroid Build Coastguard Worker
2382*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("CertGetCertificateChain returned: %s", http_sspi_strerror(error, sizeof(error), status)));
2383*5e7646d2SAndroid Build Coastguard Worker
2384*5e7646d2SAndroid Build Coastguard Worker LocalFree(commonNameUnicode);
2385*5e7646d2SAndroid Build Coastguard Worker return (status);
2386*5e7646d2SAndroid Build Coastguard Worker }
2387*5e7646d2SAndroid Build Coastguard Worker
2388*5e7646d2SAndroid Build Coastguard Worker /*
2389*5e7646d2SAndroid Build Coastguard Worker * Validate certificate chain.
2390*5e7646d2SAndroid Build Coastguard Worker */
2391*5e7646d2SAndroid Build Coastguard Worker
2392*5e7646d2SAndroid Build Coastguard Worker ZeroMemory(&httpsPolicy, sizeof(HTTPSPolicyCallbackData));
2393*5e7646d2SAndroid Build Coastguard Worker httpsPolicy.cbStruct = sizeof(HTTPSPolicyCallbackData);
2394*5e7646d2SAndroid Build Coastguard Worker httpsPolicy.dwAuthType = AUTHTYPE_SERVER;
2395*5e7646d2SAndroid Build Coastguard Worker httpsPolicy.fdwChecks = dwCertFlags;
2396*5e7646d2SAndroid Build Coastguard Worker httpsPolicy.pwszServerName = commonNameUnicode;
2397*5e7646d2SAndroid Build Coastguard Worker
2398*5e7646d2SAndroid Build Coastguard Worker memset(&policyPara, 0, sizeof(policyPara));
2399*5e7646d2SAndroid Build Coastguard Worker policyPara.cbSize = sizeof(policyPara);
2400*5e7646d2SAndroid Build Coastguard Worker policyPara.pvExtraPolicyPara = &httpsPolicy;
2401*5e7646d2SAndroid Build Coastguard Worker
2402*5e7646d2SAndroid Build Coastguard Worker memset(&policyStatus, 0, sizeof(policyStatus));
2403*5e7646d2SAndroid Build Coastguard Worker policyStatus.cbSize = sizeof(policyStatus);
2404*5e7646d2SAndroid Build Coastguard Worker
2405*5e7646d2SAndroid Build Coastguard Worker if (!CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL, chainContext, &policyPara, &policyStatus))
2406*5e7646d2SAndroid Build Coastguard Worker {
2407*5e7646d2SAndroid Build Coastguard Worker status = GetLastError();
2408*5e7646d2SAndroid Build Coastguard Worker
2409*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("CertVerifyCertificateChainPolicy returned %s", http_sspi_strerror(error, sizeof(error), status)));
2410*5e7646d2SAndroid Build Coastguard Worker }
2411*5e7646d2SAndroid Build Coastguard Worker else if (policyStatus.dwError)
2412*5e7646d2SAndroid Build Coastguard Worker status = policyStatus.dwError;
2413*5e7646d2SAndroid Build Coastguard Worker else
2414*5e7646d2SAndroid Build Coastguard Worker status = SEC_E_OK;
2415*5e7646d2SAndroid Build Coastguard Worker
2416*5e7646d2SAndroid Build Coastguard Worker if (chainContext)
2417*5e7646d2SAndroid Build Coastguard Worker CertFreeCertificateChain(chainContext);
2418*5e7646d2SAndroid Build Coastguard Worker
2419*5e7646d2SAndroid Build Coastguard Worker if (commonNameUnicode)
2420*5e7646d2SAndroid Build Coastguard Worker LocalFree(commonNameUnicode);
2421*5e7646d2SAndroid Build Coastguard Worker
2422*5e7646d2SAndroid Build Coastguard Worker return (status);
2423*5e7646d2SAndroid Build Coastguard Worker }
2424