int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx) { int i, n; const unsigned char *p; next_io: if (!(rctx->state & OHS_NOREAD)) { n = BIO_read(rctx->io, rctx->iobuf, rctx->iobuflen); if (n <= 0) { if (BIO_should_retry(rctx->io)) return -1; return 0; } /* Write data to memory BIO */ if (BIO_write(rctx->mem, rctx->iobuf, n) != n) return 0; } switch(rctx->state) { case OHS_ASN1_WRITE: n = BIO_get_mem_data(rctx->mem, &p); i = BIO_write(rctx->io, p + (n - rctx->asn1_len), rctx->asn1_len); if (i <= 0) { if (BIO_should_retry(rctx->io)) return -1; rctx->state = OHS_ERROR; return 0; } rctx->asn1_len -= i; if (rctx->asn1_len > 0) goto next_io; rctx->state = OHS_ASN1_FLUSH; (void)BIO_reset(rctx->mem); case OHS_ASN1_FLUSH: i = BIO_flush(rctx->io); if (i > 0) { rctx->state = OHS_FIRSTLINE; goto next_io; } if (BIO_should_retry(rctx->io)) return -1; rctx->state = OHS_ERROR; return 0; case OHS_ERROR: return 0; case OHS_FIRSTLINE: case OHS_HEADERS: /* Attempt to read a line in */ next_line: /* Due to &%^*$" memory BIO behaviour with BIO_gets we * have to check there's a complete line in there before * calling BIO_gets or we'll just get a partial read. */ n = BIO_get_mem_data(rctx->mem, &p); if ((n <= 0) || !TINYCLR_SSL_MEMCHR(p, '\n', n)) { if (n >= rctx->iobuflen) { rctx->state = OHS_ERROR; return 0; } goto next_io; } n = BIO_gets(rctx->mem, (char *)rctx->iobuf, rctx->iobuflen); if (n <= 0) { if (BIO_should_retry(rctx->mem)) goto next_io; rctx->state = OHS_ERROR; return 0; } /* Don't allow excessive lines */ if (n == rctx->iobuflen) { rctx->state = OHS_ERROR; return 0; } /* First line */ if (rctx->state == OHS_FIRSTLINE) { if (parse_http_line1((char *)rctx->iobuf)) { rctx->state = OHS_HEADERS; goto next_line; } else { rctx->state = OHS_ERROR; return 0; } } else { /* Look for blank line: end of headers */ for (p = rctx->iobuf; *p; p++) { if ((*p != '\r') && (*p != '\n')) break; } if (*p) goto next_line; rctx->state = OHS_ASN1_HEADER; } /* Fall thru */ case OHS_ASN1_HEADER: /* Now reading ASN1 header: can read at least 6 bytes which * is more than enough for any valid ASN1 SEQUENCE header */ n = BIO_get_mem_data(rctx->mem, &p); if (n < 6) goto next_io; /* Check it is an ASN1 SEQUENCE */ if (*p++ != (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED)) { rctx->state = OHS_ERROR; return 0; } /* Check out length field */ if (*p & 0x80) { n = *p & 0x7F; /* Not NDEF or excessive length */ if (!n || (n > 4)) { rctx->state = OHS_ERROR; return 0; } p++; rctx->asn1_len = 0; for (i = 0; i < n; i++) { rctx->asn1_len <<= 8; rctx->asn1_len |= *p++; } if (rctx->asn1_len > OCSP_MAX_REQUEST_LENGTH) { rctx->state = OHS_ERROR; return 0; } rctx->asn1_len += n + 2; } else rctx->asn1_len = *p + 2; rctx->state = OHS_ASN1_CONTENT; /* Fall thru */ case OHS_ASN1_CONTENT: n = BIO_get_mem_data(rctx->mem, &p); if (n < (int)rctx->asn1_len) goto next_io; *presp = d2i_OCSP_RESPONSE(NULL, &p, rctx->asn1_len); if (*presp) { rctx->state = OHS_DONE; return 1; } rctx->state = OHS_ERROR; return 0; break; case OHS_DONE: return 1; } return 0; }
int main(int argc, char *argv[]) { char *port = "*:4433"; BIO *in = NULL; BIO *ssl_bio, *tmp; SSL_CTX *ctx; SSL_CONF_CTX *cctx = NULL; CONF *conf = NULL; STACK_OF(CONF_VALUE) *sect = NULL; CONF_VALUE *cnf; long errline = -1; char buf[512]; int ret = 1, i; SSL_load_error_strings(); /* Add ciphers and message digests */ OpenSSL_add_ssl_algorithms(); conf = NCONF_new(NULL); if (NCONF_load(conf, "accept.cnf", &errline) <= 0) { if (errline <= 0) fprintf(stderr, "Error processing config file\n"); else fprintf(stderr, "Error on line %ld\n", errline); goto err; } sect = NCONF_get_section(conf, "default"); if (sect == NULL) { fprintf(stderr, "Error retrieving default section\n"); goto err; } ctx = SSL_CTX_new(TLS_server_method()); cctx = SSL_CONF_CTX_new(); SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER); SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE); SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE); SSL_CONF_CTX_set_ssl_ctx(cctx, ctx); for (i = 0; i < sk_CONF_VALUE_num(sect); i++) { int rv; cnf = sk_CONF_VALUE_value(sect, i); rv = SSL_CONF_cmd(cctx, cnf->name, cnf->value); if (rv > 0) continue; if (rv != -2) { fprintf(stderr, "Error processing %s = %s\n", cnf->name, cnf->value); ERR_print_errors_fp(stderr); goto err; } if (strcmp(cnf->name, "Port") == 0) { port = cnf->value; } else { fprintf(stderr, "Unknown configuration option %s\n", cnf->name); goto err; } } if (!SSL_CONF_CTX_finish(cctx)) { fprintf(stderr, "Finish error\n"); ERR_print_errors_fp(stderr); goto err; } /* Setup server side SSL bio */ ssl_bio = BIO_new_ssl(ctx, 0); if ((in = BIO_new_accept(port)) == NULL) goto err; /* * This means that when a new connection is accepted on 'in', The ssl_bio * will be 'duplicated' and have the new socket BIO push into it. * Basically it means the SSL BIO will be automatically setup */ BIO_set_accept_bios(in, ssl_bio); again: /* * The first call will setup the accept socket, and the second will get a * socket. In this loop, the first actual accept will occur in the * BIO_read() function. */ if (BIO_do_accept(in) <= 0) goto err; for (;;) { i = BIO_read(in, buf, 512); if (i == 0) { /* * If we have finished, remove the underlying BIO stack so the * next time we call any function for this BIO, it will attempt * to do an accept */ printf("Done\n"); tmp = BIO_pop(in); BIO_free_all(tmp); goto again; } if (i < 0) { if (BIO_should_retry(in)) continue; goto err; } fwrite(buf, 1, i, stdout); fflush(stdout); } ret = 0; err: if (ret) { ERR_print_errors_fp(stderr); } BIO_free(in); exit(ret); return (!ret); }
/* Send the OCSP request serialized into BIO 'request' to the * responder at given server given by URI. Returns socket object or * NULL on error. */ static apr_socket_t *send_request(BIO *request, const apr_uri_t *uri, apr_interval_time_t timeout, conn_rec *c, apr_pool_t *p, const apr_uri_t *proxy_uri) { apr_status_t rv; apr_sockaddr_t *sa; apr_socket_t *sd; char buf[HUGE_STRING_LEN]; int len; const apr_uri_t *next_hop_uri; if (proxy_uri) { next_hop_uri = proxy_uri; } else { next_hop_uri = uri; } rv = apr_sockaddr_info_get(&sa, next_hop_uri->hostname, APR_UNSPEC, next_hop_uri->port, 0, p); if (rv) { ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01972) "could not resolve address of %s %s", proxy_uri ? "proxy" : "OCSP responder", next_hop_uri->hostinfo); return NULL; } /* establish a connection to the OCSP responder */ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01973) "connecting to %s '%s'", proxy_uri ? "proxy" : "OCSP responder", uri->hostinfo); /* Cycle through address until a connect() succeeds. */ for (; sa; sa = sa->next) { rv = apr_socket_create(&sd, sa->family, SOCK_STREAM, APR_PROTO_TCP, p); if (rv == APR_SUCCESS) { apr_socket_timeout_set(sd, timeout); rv = apr_socket_connect(sd, sa); if (rv == APR_SUCCESS) { break; } apr_socket_close(sd); } } if (sa == NULL) { ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01974) "could not connect to %s '%s'", proxy_uri ? "proxy" : "OCSP responder", next_hop_uri->hostinfo); return NULL; } /* send the request and get a response */ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01975) "sending request to OCSP responder"); while ((len = BIO_read(request, buf, sizeof buf)) > 0) { char *wbuf = buf; apr_size_t remain = len; do { apr_size_t wlen = remain; rv = apr_socket_send(sd, wbuf, &wlen); wbuf += remain; remain -= wlen; } while (rv == APR_SUCCESS && remain > 0); if (rv) { apr_socket_close(sd); ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01976) "failed to send request to OCSP responder '%s'", uri->hostinfo); return NULL; } } return sd; }
MONO_API int mono_btls_bio_read (BIO *bio, void *data, int len) { return BIO_read (bio, data, len); }
static void https_add_ssl_entries(connection *con) { X509 *xs; X509_NAME *xn; X509_NAME_ENTRY *xe; int i, nentries; if ( SSL_get_verify_result(con->ssl) != X509_V_OK || !(xs = SSL_get_peer_certificate(con->ssl)) ) { return; } xn = X509_get_subject_name(xs); for (i = 0, nentries = X509_NAME_entry_count(xn); i < nentries; ++i) { int xobjnid; const char * xobjsn; data_string *envds; if (!(xe = X509_NAME_get_entry(xn, i))) { continue; } xobjnid = OBJ_obj2nid((ASN1_OBJECT*)X509_NAME_ENTRY_get_object(xe)); xobjsn = OBJ_nid2sn(xobjnid); if (!xobjsn) { continue; } if (NULL == (envds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) { envds = data_string_init(); } buffer_copy_string_len(envds->key, CONST_STR_LEN("SSL_CLIENT_S_DN_")); buffer_append_string(envds->key, xobjsn); buffer_copy_string_len( envds->value, (const char *)xe->value->data, xe->value->length ); /* pick one of the exported values as "authed user", for example * ssl.verifyclient.username = "******" or "SSL_CLIENT_S_DN_emailAddress" */ if (buffer_is_equal(con->conf.ssl_verifyclient_username, envds->key)) { buffer_copy_string_buffer(con->authed_user, envds->value); } array_insert_unique(con->environment, (data_unset *)envds); } if (con->conf.ssl_verifyclient_export_cert) { BIO *bio; if (NULL != (bio = BIO_new(BIO_s_mem()))) { data_string *envds; int n; PEM_write_bio_X509(bio, xs); n = BIO_pending(bio); if (NULL == (envds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) { envds = data_string_init(); } buffer_copy_string_len(envds->key, CONST_STR_LEN("SSL_CLIENT_CERT")); buffer_prepare_copy(envds->value, n+1); BIO_read(bio, envds->value->ptr, n); BIO_free(bio); envds->value->ptr[n] = '\0'; envds->value->used = n+1; array_insert_unique(con->environment, (data_unset *)envds); } } X509_free(xs); }
apr_hash_t *serf_ssl_cert_certificate( const serf_ssl_certificate_t *cert, apr_pool_t *pool) { apr_hash_t *tgt = apr_hash_make(pool); unsigned int md_size, i; unsigned char md[EVP_MAX_MD_SIZE]; BIO *bio; STACK_OF(GENERAL_NAME) *names; /* sha1 fingerprint */ if (X509_digest(cert->ssl_cert, EVP_sha1(), md, &md_size)) { const char hex[] = "0123456789ABCDEF"; char fingerprint[EVP_MAX_MD_SIZE * 3]; for (i=0; i<md_size; i++) { fingerprint[3*i] = hex[(md[i] & 0xf0) >> 4]; fingerprint[(3*i)+1] = hex[(md[i] & 0x0f)]; fingerprint[(3*i)+2] = ':'; } if (md_size > 0) fingerprint[(3*(md_size-1))+2] = '\0'; else fingerprint[0] = '\0'; apr_hash_set(tgt, "sha1", APR_HASH_KEY_STRING, apr_pstrdup(pool, fingerprint)); } /* set expiry dates */ bio = BIO_new(BIO_s_mem()); if (bio) { ASN1_TIME *notBefore, *notAfter; char buf[256]; memset (buf, 0, sizeof (buf)); notBefore = X509_get_notBefore(cert->ssl_cert); if (ASN1_TIME_print(bio, notBefore)) { BIO_read(bio, buf, 255); apr_hash_set(tgt, "notBefore", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf)); } memset (buf, 0, sizeof (buf)); notAfter = X509_get_notAfter(cert->ssl_cert); if (ASN1_TIME_print(bio, notAfter)) { BIO_read(bio, buf, 255); apr_hash_set(tgt, "notAfter", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf)); } } BIO_free(bio); /* Get subjectAltNames */ names = X509_get_ext_d2i(cert->ssl_cert, NID_subject_alt_name, NULL, NULL); if (names) { int names_count = sk_GENERAL_NAME_num(names); apr_array_header_t *san_arr = apr_array_make(pool, names_count, sizeof(char*)); apr_hash_set(tgt, "subjectAltName", APR_HASH_KEY_STRING, san_arr); for (i = 0; i < names_count; i++) { char *p = NULL; GENERAL_NAME *nm = sk_GENERAL_NAME_value(names, i); switch (nm->type) { case GEN_DNS: p = apr_pstrmemdup(pool, nm->d.ia5->data, nm->d.ia5->length); break; default: /* Don't know what to do - skip. */ break; } if (p) { APR_ARRAY_PUSH(san_arr, char*) = p; } } sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); } return tgt; }
static int process_pci_value(CONF_VALUE *val, ASN1_OBJECT **language, ASN1_INTEGER **pathlen, ASN1_OCTET_STRING **policy) { int free_policy = 0; if (strcmp(val->name, "language") == 0) { if (*language) { X509V3err(X509V3_F_PROCESS_PCI_VALUE,X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED); X509V3_conf_err(val); return 0; } if (!(*language = OBJ_txt2obj(val->value, 0))) { X509V3err(X509V3_F_PROCESS_PCI_VALUE,X509V3_R_INVALID_OBJECT_IDENTIFIER); X509V3_conf_err(val); return 0; } } else if (strcmp(val->name, "pathlen") == 0) { if (*pathlen) { X509V3err(X509V3_F_PROCESS_PCI_VALUE,X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED); X509V3_conf_err(val); return 0; } if (!X509V3_get_value_int(val, pathlen)) { X509V3err(X509V3_F_PROCESS_PCI_VALUE,X509V3_R_POLICY_PATH_LENGTH); X509V3_conf_err(val); return 0; } } else if (strcmp(val->name, "policy") == 0) { unsigned char *tmp_data = NULL; long val_len; if (!*policy) { *policy = ASN1_OCTET_STRING_new(); if (!*policy) { X509V3err(X509V3_F_PROCESS_PCI_VALUE,ERR_R_MALLOC_FAILURE); X509V3_conf_err(val); return 0; } free_policy = 1; } if (strncmp(val->value, "hex:", 4) == 0) { unsigned char *tmp_data2 = string_to_hex(val->value + 4, &val_len); if (!tmp_data2) { X509V3err(X509V3_F_PROCESS_PCI_VALUE,X509V3_R_ILLEGAL_HEX_DIGIT); X509V3_conf_err(val); goto err; } tmp_data = OPENSSL_realloc((*policy)->data, (*policy)->length + val_len + 1); if (tmp_data) { (*policy)->data = tmp_data; memcpy(&(*policy)->data[(*policy)->length], tmp_data2, val_len); (*policy)->length += val_len; (*policy)->data[(*policy)->length] = '\0'; } else { OPENSSL_free(tmp_data2); /* realloc failure implies the original data space is b0rked too! */ (*policy)->data = NULL; (*policy)->length = 0; X509V3err(X509V3_F_PROCESS_PCI_VALUE,ERR_R_MALLOC_FAILURE); X509V3_conf_err(val); goto err; } OPENSSL_free(tmp_data2); } else if (strncmp(val->value, "file:", 5) == 0) { unsigned char buf[2048]; int n; BIO *b = BIO_new_file(val->value + 5, "r"); if (!b) { X509V3err(X509V3_F_PROCESS_PCI_VALUE,ERR_R_BIO_LIB); X509V3_conf_err(val); goto err; } while((n = BIO_read(b, buf, sizeof(buf))) > 0 || (n == 0 && BIO_should_retry(b))) { if (!n) continue; tmp_data = OPENSSL_realloc((*policy)->data, (*policy)->length + n + 1); if (!tmp_data) break; (*policy)->data = tmp_data; memcpy(&(*policy)->data[(*policy)->length], buf, n); (*policy)->length += n; (*policy)->data[(*policy)->length] = '\0'; } BIO_free_all(b); if (n < 0) { X509V3err(X509V3_F_PROCESS_PCI_VALUE,ERR_R_BIO_LIB); X509V3_conf_err(val); goto err; } } else if (strncmp(val->value, "text:", 5) == 0) { val_len = strlen(val->value + 5); tmp_data = OPENSSL_realloc((*policy)->data, (*policy)->length + val_len + 1); if (tmp_data) { (*policy)->data = tmp_data; memcpy(&(*policy)->data[(*policy)->length], val->value + 5, val_len); (*policy)->length += val_len; (*policy)->data[(*policy)->length] = '\0'; } else { /* realloc failure implies the original data space is b0rked too! */ (*policy)->data = NULL; (*policy)->length = 0; X509V3err(X509V3_F_PROCESS_PCI_VALUE,ERR_R_MALLOC_FAILURE); X509V3_conf_err(val); goto err; } } else { X509V3err(X509V3_F_PROCESS_PCI_VALUE,X509V3_R_INCORRECT_POLICY_SYNTAX_TAG); X509V3_conf_err(val); goto err; } if (!tmp_data) { X509V3err(X509V3_F_PROCESS_PCI_VALUE,ERR_R_MALLOC_FAILURE); X509V3_conf_err(val); goto err; } } return 1; err: if (free_policy) { ASN1_OCTET_STRING_free(*policy); *policy = NULL; } return 0; }
static int crlfbuffer_read(BIO *b, char *out, int outl) { int ret=0; BIO_CRLFBUFFER_CTX *ctx; if (out == NULL) return(0); if (b->next_bio == NULL) return(0); ctx=(BIO_CRLFBUFFER_CTX *)b->ptr; // First copy what's in the current buffer int i = ctx->ibuf_len; if (i != 0) { if (i > outl) i = outl; memcpy(out, &(ctx->ibuf[ctx->ibuf_off]), i); ctx->ibuf_off += i; ctx->ibuf_len -= i; ret += i; outl -= i; out += i; } // Now read any remaining direct from source if (outl > 0) ret += BIO_read(b->next_bio,out,outl); BIO_clear_retry_flags(b); BIO_copy_next_retry(b); if (ret > 0) { BIO_CRLFBUFFER_CTX *new_ctx = (BIO_CRLFBUFFER_CTX *)b->ptr; char *p = out; char *q = out; int qlen = 0; int plen = ret; while(plen > 0) { if (*p == '\r') { p++; plen--; *q++ = '\n'; qlen++; new_ctx->got_cr = true; } else if (*p == '\n') { p++; plen--; if (!new_ctx->got_cr) { *q++ = '\n'; qlen++; } new_ctx->got_cr = false; } else { *q++ = *p++; plen--; qlen++; new_ctx->got_cr = false; } } *q++ = 0; ret = qlen; } return(ret); }
static int read_n(SSL *s, unsigned int n, unsigned int max, unsigned int extend) { int i,off,newb; /* if there is stuff still in the buffer from a previous read, * and there is more than we want, take some. */ if (s->s2->rbuf_left >= (int)n) { if (extend) s->packet_length+=n; else { s->packet= &(s->s2->rbuf[s->s2->rbuf_offs]); s->packet_length=n; } s->s2->rbuf_left-=n; s->s2->rbuf_offs+=n; return(n); } if (!s->read_ahead) max=n; if (max > (unsigned int)(SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2)) max=SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2; /* Else we want more than we have. * First, if there is some left or we want to extend */ off=0; if ((s->s2->rbuf_left != 0) || ((s->packet_length != 0) && extend)) { newb=s->s2->rbuf_left; if (extend) { off=s->packet_length; if (s->packet != s->s2->rbuf) memcpy(s->s2->rbuf,s->packet, (unsigned int)newb+off); } else if (s->s2->rbuf_offs != 0) { memcpy(s->s2->rbuf,&(s->s2->rbuf[s->s2->rbuf_offs]), (unsigned int)newb); s->s2->rbuf_offs=0; } s->s2->rbuf_left=0; } else newb=0; /* off is the offset to start writing too. * r->s2->rbuf_offs is the 'unread data', now 0. * newb is the number of new bytes so far */ s->packet=s->s2->rbuf; while (newb < (int)n) { clear_sys_error(); if (s->rbio != NULL) { s->rwstate=SSL_READING; i=BIO_read(s->rbio,(char *)&(s->s2->rbuf[off+newb]), max-newb); } else { SSLerr(SSL_F_READ_N,SSL_R_READ_BIO_NOT_SET); i= -1; } #ifdef PKT_DEBUG if (s->debug & 0x01) sleep(1); #endif if (i <= 0) { s->s2->rbuf_left+=newb; return(i); } newb+=i; } /* record unread data */ if (newb > (int)n) { s->s2->rbuf_offs=n+off; s->s2->rbuf_left=newb-n; } else { s->s2->rbuf_offs=0; s->s2->rbuf_left=0; } if (extend) s->packet_length+=n; else s->packet_length=n; s->rwstate=SSL_NOTHING; return(n); }
int rsautl_main(int argc, char **argv) { ENGINE *e = NULL; BIO *in = NULL, *out = NULL; char *infile = NULL, *outfile = NULL; #ifndef OPENSSL_NO_ENGINE char *engine = NULL; #endif char *keyfile = NULL; char rsa_mode = RSA_VERIFY, key_type = KEY_PRIVKEY; int keyform = FORMAT_PEM; char need_priv = 0, badarg = 0, rev = 0; char hexdump = 0, asn1parse = 0; X509 *x; EVP_PKEY *pkey = NULL; RSA *rsa = NULL; unsigned char *rsa_in = NULL, *rsa_out = NULL, pad; char *passargin = NULL, *passin = NULL; int rsa_inlen, rsa_outlen = 0; int keysize; int ret = 1; argc--; argv++; pad = RSA_PKCS1_PADDING; while (argc >= 1) { if (!strcmp(*argv, "-in")) { if (--argc < 1) badarg = 1; else infile = *(++argv); } else if (!strcmp(*argv, "-out")) { if (--argc < 1) badarg = 1; else outfile = *(++argv); } else if (!strcmp(*argv, "-inkey")) { if (--argc < 1) badarg = 1; else keyfile = *(++argv); } else if (!strcmp(*argv, "-passin")) { if (--argc < 1) badarg = 1; else passargin = *(++argv); } else if (strcmp(*argv, "-keyform") == 0) { if (--argc < 1) badarg = 1; else keyform = str2fmt(*(++argv)); #ifndef OPENSSL_NO_ENGINE } else if (!strcmp(*argv, "-engine")) { if (--argc < 1) badarg = 1; else engine = *(++argv); #endif } else if (!strcmp(*argv, "-pubin")) { key_type = KEY_PUBKEY; } else if (!strcmp(*argv, "-certin")) { key_type = KEY_CERT; } else if (!strcmp(*argv, "-asn1parse")) asn1parse = 1; else if (!strcmp(*argv, "-hexdump")) hexdump = 1; else if (!strcmp(*argv, "-raw")) pad = RSA_NO_PADDING; else if (!strcmp(*argv, "-oaep")) pad = RSA_PKCS1_OAEP_PADDING; else if (!strcmp(*argv, "-ssl")) pad = RSA_SSLV23_PADDING; else if (!strcmp(*argv, "-pkcs")) pad = RSA_PKCS1_PADDING; else if (!strcmp(*argv, "-x931")) pad = RSA_X931_PADDING; else if (!strcmp(*argv, "-sign")) { rsa_mode = RSA_SIGN; need_priv = 1; } else if (!strcmp(*argv, "-verify")) rsa_mode = RSA_VERIFY; else if (!strcmp(*argv, "-rev")) rev = 1; else if (!strcmp(*argv, "-encrypt")) rsa_mode = RSA_ENCRYPT; else if (!strcmp(*argv, "-decrypt")) { rsa_mode = RSA_DECRYPT; need_priv = 1; } else badarg = 1; if (badarg) { usage(); goto end; } argc--; argv++; } if (need_priv && (key_type != KEY_PRIVKEY)) { BIO_printf(bio_err, "A private key is needed for this operation\n"); goto end; } #ifndef OPENSSL_NO_ENGINE e = setup_engine(bio_err, engine, 0); #endif if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } switch (key_type) { case KEY_PRIVKEY: pkey = load_key(bio_err, keyfile, keyform, 0, passin, e, "Private Key"); break; case KEY_PUBKEY: pkey = load_pubkey(bio_err, keyfile, keyform, 0, NULL, e, "Public Key"); break; case KEY_CERT: x = load_cert(bio_err, keyfile, keyform, NULL, e, "Certificate"); if (x) { pkey = X509_get_pubkey(x); X509_free(x); } break; } if (!pkey) { return 1; } rsa = EVP_PKEY_get1_RSA(pkey); EVP_PKEY_free(pkey); if (!rsa) { BIO_printf(bio_err, "Error getting RSA key\n"); ERR_print_errors(bio_err); goto end; } if (infile) { if (!(in = BIO_new_file(infile, "rb"))) { BIO_printf(bio_err, "Error Reading Input File\n"); ERR_print_errors(bio_err); goto end; } } else in = BIO_new_fp(stdin, BIO_NOCLOSE); if (outfile) { if (!(out = BIO_new_file(outfile, "wb"))) { BIO_printf(bio_err, "Error Reading Output File\n"); ERR_print_errors(bio_err); goto end; } } else { out = BIO_new_fp(stdout, BIO_NOCLOSE); } keysize = RSA_size(rsa); rsa_in = reallocarray(NULL, keysize, 2); rsa_out = malloc(keysize); /* Read the input data */ rsa_inlen = BIO_read(in, rsa_in, keysize * 2); if (rsa_inlen <= 0) { BIO_printf(bio_err, "Error reading input Data\n"); exit(1); } if (rev) { int i; unsigned char ctmp; for (i = 0; i < rsa_inlen / 2; i++) { ctmp = rsa_in[i]; rsa_in[i] = rsa_in[rsa_inlen - 1 - i]; rsa_in[rsa_inlen - 1 - i] = ctmp; } } switch (rsa_mode) { case RSA_VERIFY: rsa_outlen = RSA_public_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); break; case RSA_SIGN: rsa_outlen = RSA_private_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); break; case RSA_ENCRYPT: rsa_outlen = RSA_public_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); break; case RSA_DECRYPT: rsa_outlen = RSA_private_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, pad); break; } if (rsa_outlen <= 0) { BIO_printf(bio_err, "RSA operation error\n"); ERR_print_errors(bio_err); goto end; } ret = 0; if (asn1parse) { if (!ASN1_parse_dump(out, rsa_out, rsa_outlen, 1, -1)) { ERR_print_errors(bio_err); } } else if (hexdump) BIO_dump(out, (char *) rsa_out, rsa_outlen); else BIO_write(out, rsa_out, rsa_outlen); end: RSA_free(rsa); BIO_free(in); BIO_free_all(out); free(rsa_in); free(rsa_out); free(passin); return ret; }
static void ssl_log_cert_error(const char *file, int line, int level, apr_status_t rv, const server_rec *s, const conn_rec *c, const request_rec *r, apr_pool_t *p, X509 *cert, const char *format, va_list ap) { char buf[HUGE_STRING_LEN]; int msglen, n; char *name; apr_vsnprintf(buf, sizeof buf, format, ap); msglen = strlen(buf); if (cert) { BIO *bio = BIO_new(BIO_s_mem()); if (bio) { /* * Limit the maximum length of the subject and issuer DN strings * in the log message. 300 characters should always be sufficient * for holding both the timestamp, module name, pid etc. stuff * at the beginning of the line and the trailing information about * serial, notbefore and notafter. */ int maxdnlen = (HUGE_STRING_LEN - msglen - 300) / 2; BIO_puts(bio, " [subject: "); name = modssl_X509_NAME_to_string(p, X509_get_subject_name(cert), maxdnlen); if (!strIsEmpty(name)) { BIO_puts(bio, name); } else { BIO_puts(bio, "-empty-"); } BIO_puts(bio, " / issuer: "); name = modssl_X509_NAME_to_string(p, X509_get_issuer_name(cert), maxdnlen); if (!strIsEmpty(name)) { BIO_puts(bio, name); } else { BIO_puts(bio, "-empty-"); } BIO_puts(bio, " / serial: "); if (i2a_ASN1_INTEGER(bio, X509_get_serialNumber(cert)) == -1) BIO_puts(bio, "(ERROR)"); BIO_puts(bio, " / notbefore: "); ASN1_TIME_print(bio, X509_get_notBefore(cert)); BIO_puts(bio, " / notafter: "); ASN1_TIME_print(bio, X509_get_notAfter(cert)); BIO_puts(bio, "]"); n = BIO_read(bio, buf + msglen, sizeof buf - msglen - 1); if (n > 0) buf[msglen + n] = '\0'; BIO_free(bio); } } else { apr_snprintf(buf + msglen, sizeof buf - msglen, " [certificate: -not available-]"); } if (r) { ap_log_rerror(file, line, APLOG_MODULE_INDEX, level, rv, r, "%s", buf); } else if (c) { ap_log_cerror(file, line, APLOG_MODULE_INDEX, level, rv, c, "%s", buf); } else if (s) { ap_log_error(file, line, APLOG_MODULE_INDEX, level, rv, s, "%s", buf); } }
int proxyhandler(BIO *cbio) { BIO *mbio = NULL, *sbio = NULL; char *mptr = NULL; long mlen; int cfd, sfd, len = 0, found = 0; fd_set rfds; char buf[1024]; struct sockaddr_in caddr; char auth[1024] = {0}; int cl = 0; mbio = BIO_new(BIO_s_mem()); for(len = 0; ; len = 0) { while(len < sizeof(buf)) { if(BIO_read(cbio, buf + len, 1) != 1) return -1; if(buf[len++] == '\n') break; } buf[--len] = '\0'; if(len && (buf[len - 1] == '\r')) buf[len - 1] = '\0'; if(!buf[0]) break; if(!strncasecmp(buf, "X-Forwarded-For: ", strlen("X-Forwarded-For: "))) found |= FOUND_XFF; if(!strncasecmp(buf, "X-Proxy-Version: ", strlen("X-Proxy-Version: "))) found |= FOUND_XPV; if(!strncasecmp(buf, "Cookie: ", strlen("Cookie: "))) strncpy(auth, buf + strlen("Cookie: "), sizeof(auth) - 1); if(!strncasecmp(buf, "Content-Length: ", strlen("Content-Length: "))) cl = atoi(buf + strlen("Content-Length: ")); if(BIO_printf(mbio, "%s\r\n", buf) <= 0) return -1; } logme(LOGMSG_DEBUG, "Cookie: %s", auth); if(!strcmp(auth, conf.cookie)) return commandhandler(cbio, cl); sbio = BIO_new_connect(conf.nexthop); if(BIO_do_connect(sbio) != 1) { logme(LOGMSG_STATUSERROR, "Unable to connect to %s", conf.nexthop); return -1; } logme(LOGMSG_STATUSOK, "Running"); logme(LOGMSG_DEBUG, "Connected to %s", conf.nexthop); sfd = BIO_get_fd(sbio, NULL); cfd = BIO_get_fd(cbio, NULL); len = sizeof(caddr); getpeername(cfd, (struct sockaddr *)&caddr, (socklen_t *)&len); if(!(found & FOUND_COOKIE)) logme(LOGMSG_DEBUG, "New session forwarded for %s", inet_ntoa(caddr.sin_addr)); if((mlen = BIO_get_mem_data(mbio, &mptr)) > 0) BIO_write(sbio, mptr, mlen); if(!(found & FOUND_XFF)) if(BIO_printf(sbio, "X-Forwarded-For: %s\r\n", inet_ntoa(caddr.sin_addr)) <= 0) return -1; if(!(found & FOUND_XPV)) if(BIO_printf(sbio, "X-Proxy-Version: %s\r\n", conf.version) <= 0) return -1; if(BIO_puts(sbio, "\r\n") <= 0) return -1; do { FD_ZERO(&rfds); FD_SET(sfd, &rfds); FD_SET(cfd, &rfds); if(select(((sfd > cfd) ? sfd : cfd) + 1, &rfds, NULL, NULL, NULL) == -1) return -1; if(FD_ISSET(sfd, &rfds)) { if((len = BIO_read(sbio, buf, sizeof(buf))) > 0) if(BIO_write(cbio, buf, len) <= 0) return -1; } else if(FD_ISSET(cfd, &rfds)) { if((len = BIO_read(cbio, buf, sizeof(buf))) > 0) if(BIO_write(sbio, buf, len) <= 0) return -1; } } while(len > 0); return 0; }
int commandhandler(BIO *cbio, int cl) { BIO *bbody = NULL, *bbase64 = NULL, *bcrypt = NULL; int ret = -1; char buf[100 * 1024]; json_object *config = NULL; unsigned char iv[16]; BIO *bmem = NULL; char *bptr = NULL, *c = NULL; long blen = 0; char *command = NULL; logme(LOGMSG_DEBUG, "commandhandler (cl=%d)", cl); do { if(!(bmem = BIO_new(BIO_s_mem()))) break; if(!(bbody = BIO_new(BIO_s_mem()))) break; if(!(bbase64 = BIO_new(BIO_f_base64()))) break; BIO_set_flags(bbase64, BIO_FLAGS_BASE64_NO_NL); if(!(bcrypt = BIO_new(BIO_f_cipher()))) break; memset(iv, 0x00, sizeof(iv)); BIO_set_cipher(bcrypt, EVP_get_cipherbyname("aes-128-cbc"), (unsigned char *)conf.key, iv, 0); BIO_push(bbase64, bbody); BIO_push(bcrypt, bmem); while(blen < cl) { if((ret = BIO_read(cbio, buf, ((cl - blen) > sizeof(buf)) ? sizeof(buf) : (cl - blen))) <= 0) break; blen += ret; while((c = memchr(buf, '\n', ret)) || (c = memchr(buf, '\r', ret))) memmove(c, c + 1, --ret - (c - buf)); if(BIO_write(bbody, buf, ret) != ret) { logme(LOGMSG_DEBUG, "BIO_write error"); break; } } do { blen = BIO_read(bbase64, buf, sizeof(buf)); if(blen > 0) { BIO_write(bcrypt, buf, blen); } } while(blen > 0); (void)BIO_flush(bcrypt); blen = BIO_get_mem_data(bmem, &bptr); if(!(config = json_tokener_parse(bptr))) break; if(!(command = (char *)json_object_get_string(json_object_object_get(config, "command")))) break; logme(LOGMSG_DEBUG, "command: %s", command); if(!strcasecmp(command, "FORWARD")) { ret = command_forward(config, cbio); } else if(!strcasecmp(command, "CONFIG")) { ret = command_config(config, cbio); } else if(!strcasecmp(command, "UPGRADE")) { ret = command_upgrade(config, cbio); } else if(!strcasecmp(command, "CHECK")) { ret = command_check(config, cbio); } } while(0); if(bbody) BIO_free(bbody); if(bbase64) BIO_free(bbase64); if(bcrypt) BIO_free(bcrypt); if(bmem) BIO_free(bmem); if(config) json_object_put(config); return ret; }
TagLib::ByteVector TagLib::DecodeBase64(const TagLib::ByteVector& input) { #if USE_SECURITY_FRAMEWORK ByteVector result; CFErrorRef error; SecTransformRef decoder = SecDecodeTransformCreate(kSecBase64Encoding, &error); if(nullptr == decoder) { CFShow(error); return TagLib::ByteVector::null; } CFDataRef sourceData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)input.data(), input.size(), kCFAllocatorNull); if(nullptr == sourceData) { CFRelease(decoder), decoder = nullptr; return TagLib::ByteVector::null; } if(!SecTransformSetAttribute(decoder, kSecTransformInputAttributeName, sourceData, &error)) { CFShow(error); CFRelease(sourceData), sourceData = nullptr; CFRelease(decoder), decoder = nullptr; return TagLib::ByteVector::null; } CFTypeRef decodedData = SecTransformExecute(decoder, &error); if(nullptr == decodedData) { CFShow(error); CFRelease(sourceData), sourceData = nullptr; CFRelease(decoder), decoder = nullptr; return TagLib::ByteVector::null; } result.setData((const char *)CFDataGetBytePtr((CFDataRef)decodedData), (TagLib::uint)CFDataGetLength((CFDataRef)decodedData)); CFRelease(decodedData), decodedData = nullptr; CFRelease(sourceData), sourceData = nullptr; CFRelease(decoder), decoder = nullptr; return result; #else ByteVector result; BIO *b64 = BIO_new(BIO_f_base64()); BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); BIO *bio = BIO_new_mem_buf(reinterpret_cast<void *>(const_cast<char *>(input.data())), input.size()); bio = BIO_push(b64, bio); char inbuf [512]; int inlen; while(0 < (inlen = BIO_read(bio, inbuf, 512))) result.append(ByteVector(inbuf, inlen)); BIO_free_all(bio); return result; #endif }
static Ecore_Con_Ssl_Error _ecore_con_ssl_server_init_openssl(Ecore_Con_Server *svr) { int ret = -1; switch (svr->ssl_state) { case ECORE_CON_SSL_STATE_DONE: return ECORE_CON_SSL_ERROR_NONE; case ECORE_CON_SSL_STATE_INIT: SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl = SSL_new(svr->ssl_ctx))); SSL_ERROR_CHECK_GOTO_ERROR(!SSL_set_fd(svr->ssl, svr->fd)); SSL_set_connect_state(svr->ssl); svr->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; case ECORE_CON_SSL_STATE_HANDSHAKING: if (!svr->ssl) { DBG("Server was previously lost, going to error condition"); goto error; } ret = SSL_do_handshake(svr->ssl); svr->ssl_err = SSL_get_error(svr->ssl, ret); SSL_ERROR_CHECK_GOTO_ERROR((svr->ssl_err == SSL_ERROR_SYSCALL) || (svr->ssl_err == SSL_ERROR_SSL)); if (ret == 1) { svr->handshaking = EINA_FALSE; svr->ssl_state = ECORE_CON_SSL_STATE_DONE; } else { if (svr->ssl_err == SSL_ERROR_WANT_READ) ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ); else if (svr->ssl_err == SSL_ERROR_WANT_WRITE) ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE); return ECORE_CON_SSL_ERROR_NONE; } default: break; } #ifdef ISCOMFITOR { /* print session info into DBG */ SSL_SESSION *s; BIO *b; char log[4096]; memset(log, 0, sizeof(log)); s = SSL_get_session(svr->ssl); b = BIO_new(BIO_s_mem()); SSL_SESSION_print(b, s); while (BIO_read(b, log, sizeof(log)) > 0) DBG("%s", log); BIO_free(b); } #endif if (!svr->verify) /* not verifying certificates, so we're done! */ return ECORE_CON_SSL_ERROR_NONE; { X509 *cert; SSL_set_verify(svr->ssl, SSL_VERIFY_PEER, NULL); /* use CRL/CA lists to verify */ cert = SSL_get_peer_certificate(svr->ssl); if (cert) { char buf[256] = {0}; SSL_ERROR_CHECK_GOTO_ERROR(SSL_get_verify_result(svr->ssl)); X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_subject_alt_name, buf, sizeof(buf)); if (buf[0]) SSL_ERROR_CHECK_GOTO_ERROR(!_openssl_name_verify(buf, svr->name)); else { X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, buf, sizeof(buf)); SSL_ERROR_CHECK_GOTO_ERROR(!_openssl_name_verify(buf, svr->name)); } } } DBG("SSL certificate verification succeeded!"); return ECORE_CON_SSL_ERROR_NONE; error: _openssl_print_errors(); _ecore_con_ssl_server_shutdown_openssl(svr); return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; }
static int tls_drv_control(ErlDrvData handle, unsigned int command, char *buf, int len, char **rbuf, int rlen) { tls_data *d = (tls_data *)handle; int res; int size; ErlDrvBinary *b; X509 *cert; unsigned int flags = command; command &= 0xffff; ERR_clear_error(); switch (command) { case SET_CERTIFICATE_FILE_ACCEPT: case SET_CERTIFICATE_FILE_CONNECT: { time_t mtime = 0; SSL_CTX *ssl_ctx = hash_table_lookup(buf, &mtime); if (is_key_file_modified(buf, &mtime) || ssl_ctx == NULL) { SSL_CTX *ctx; hash_table_insert(buf, mtime, NULL); ctx = SSL_CTX_new(SSLv23_method()); die_unless(ctx, "SSL_CTX_new failed"); res = SSL_CTX_use_certificate_chain_file(ctx, buf); die_unless(res > 0, "SSL_CTX_use_certificate_file failed"); res = SSL_CTX_use_PrivateKey_file(ctx, buf, SSL_FILETYPE_PEM); die_unless(res > 0, "SSL_CTX_use_PrivateKey_file failed"); res = SSL_CTX_check_private_key(ctx); die_unless(res > 0, "SSL_CTX_check_private_key failed"); SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); SSL_CTX_set_default_verify_paths(ctx); #ifdef SSL_MODE_RELEASE_BUFFERS SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS); #endif if (command == SET_CERTIFICATE_FILE_ACCEPT) { SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE, verify_callback); } ssl_ctx = ctx; hash_table_insert(buf, mtime, ssl_ctx); } d->ssl = SSL_new(ssl_ctx); die_unless(d->ssl, "SSL_new failed"); if (flags & VERIFY_NONE) SSL_set_verify(d->ssl, SSL_VERIFY_NONE, verify_callback); d->bio_read = BIO_new(BIO_s_mem()); d->bio_write = BIO_new(BIO_s_mem()); SSL_set_bio(d->ssl, d->bio_read, d->bio_write); if (command == SET_CERTIFICATE_FILE_ACCEPT) { SSL_set_options(d->ssl, SSL_OP_NO_TICKET); SSL_set_accept_state(d->ssl); } else { SSL_set_options(d->ssl, SSL_OP_NO_SSLv2|SSL_OP_NO_TICKET); SSL_set_connect_state(d->ssl); } break; } case SET_ENCRYPTED_INPUT: die_unless(d->ssl, "SSL not initialized"); BIO_write(d->bio_read, buf, len); break; case SET_DECRYPTED_OUTPUT: die_unless(d->ssl, "SSL not initialized"); res = SSL_write(d->ssl, buf, len); if (res <= 0) { res = SSL_get_error(d->ssl, res); if (res == SSL_ERROR_WANT_READ || res == SSL_ERROR_WANT_WRITE) { b = driver_alloc_binary(1); b->orig_bytes[0] = 2; *rbuf = (char *)b; return 1; } else { die_unless(0, "SSL_write failed"); } } break; case GET_ENCRYPTED_OUTPUT: die_unless(d->ssl, "SSL not initialized"); size = BUF_SIZE + 1; rlen = 1; b = driver_alloc_binary(size); b->orig_bytes[0] = 0; while ((res = BIO_read(d->bio_write, b->orig_bytes + rlen, BUF_SIZE)) > 0) { //printf("%d bytes of encrypted data read from state machine\r\n", res); rlen += res; size += BUF_SIZE; b = driver_realloc_binary(b, size); } b = driver_realloc_binary(b, rlen); *rbuf = (char *)b; return rlen; case GET_DECRYPTED_INPUT: if (!SSL_is_init_finished(d->ssl)) { res = SSL_do_handshake(d->ssl); if (res <= 0) die_unless(SSL_get_error(d->ssl, res) == SSL_ERROR_WANT_READ, "SSL_do_handshake failed"); } else { size = BUF_SIZE + 1; rlen = 1; b = driver_alloc_binary(size); b->orig_bytes[0] = 0; while ((res = SSL_read(d->ssl, b->orig_bytes + rlen, BUF_SIZE)) > 0) { //printf("%d bytes of decrypted data read from state machine\r\n",res); rlen += res; size += BUF_SIZE; b = driver_realloc_binary(b, size); } if (res < 0) { int err = SSL_get_error(d->ssl, res); if (err == SSL_ERROR_WANT_READ) { //printf("SSL_read wants more data\r\n"); //return 0; } // TODO } b = driver_realloc_binary(b, rlen); *rbuf = (char *)b; return rlen; } break; case GET_PEER_CERTIFICATE: cert = SSL_get_peer_certificate(d->ssl); if (cert == NULL) { b = driver_alloc_binary(1); b->orig_bytes[0] = 1; *rbuf = (char *)b; return 1; } else { unsigned char *tmp_buf; rlen = i2d_X509(cert, NULL); if (rlen >= 0) { rlen++; b = driver_alloc_binary(rlen); b->orig_bytes[0] = 0; tmp_buf = (unsigned char *)&b->orig_bytes[1]; i2d_X509(cert, &tmp_buf); X509_free(cert); *rbuf = (char *)b; return rlen; } else X509_free(cert); } break; case GET_VERIFY_RESULT: b = driver_alloc_binary(1); b->orig_bytes[0] = SSL_get_verify_result(d->ssl); *rbuf = (char *)b; return 1; break; } b = driver_alloc_binary(1); b->orig_bytes[0] = 0; *rbuf = (char *)b; return 1; }
static Ecore_Con_Ssl_Error _ecore_con_ssl_client_init_openssl(Ecore_Con_Client *cl) { int ret = -1; switch (cl->ssl_state) { case ECORE_CON_SSL_STATE_DONE: return ECORE_CON_SSL_ERROR_NONE; case ECORE_CON_SSL_STATE_INIT: SSL_ERROR_CHECK_GOTO_ERROR(!(cl->ssl = SSL_new(cl->host_server->ssl_ctx))); SSL_ERROR_CHECK_GOTO_ERROR(!SSL_set_fd(cl->ssl, cl->fd)); SSL_set_accept_state(cl->ssl); cl->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; case ECORE_CON_SSL_STATE_HANDSHAKING: if (!cl->ssl) { DBG("Client was previously lost, going to error condition"); goto error; } ret = SSL_do_handshake(cl->ssl); cl->ssl_err = SSL_get_error(cl->ssl, ret); SSL_ERROR_CHECK_GOTO_ERROR((cl->ssl_err == SSL_ERROR_SYSCALL) || (cl->ssl_err == SSL_ERROR_SSL)); if (ret == 1) { cl->handshaking = EINA_FALSE; cl->ssl_state = ECORE_CON_SSL_STATE_DONE; } else { if (cl->ssl_err == SSL_ERROR_WANT_READ) ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ); else if (cl->ssl_err == SSL_ERROR_WANT_WRITE) ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE); return ECORE_CON_SSL_ERROR_NONE; } default: break; } #ifdef ISCOMFITOR { /* print session info into DBG */ SSL_SESSION *s; BIO *b; char log[4096]; memset(log, 0, sizeof(log)); s = SSL_get_session(cl->ssl); b = BIO_new(BIO_s_mem()); SSL_SESSION_print(b, s); while (BIO_read(b, log, sizeof(log)) > 0) DBG("%s", log); BIO_free(b); } #endif if (!cl->host_server->verify) /* not verifying certificates, so we're done! */ return ECORE_CON_SSL_ERROR_NONE; SSL_set_verify(cl->ssl, SSL_VERIFY_PEER, NULL); /* use CRL/CA lists to verify */ if (SSL_get_peer_certificate(cl->ssl)) SSL_ERROR_CHECK_GOTO_ERROR(SSL_get_verify_result(cl->ssl)); return ECORE_CON_SSL_ERROR_NONE; error: _openssl_print_errors(); _ecore_con_ssl_client_shutdown_openssl(cl); return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; }
static int ok_read(BIO *b, char *out, int outl) { int ret=0,i,n; BIO_OK_CTX *ctx; if (out == NULL) return(0); ctx=(BIO_OK_CTX *)b->ptr; if ((ctx == NULL) || (b->next_bio == NULL) || (b->init == 0)) return(0); while(outl > 0) { /* copy clean bytes to output buffer */ if (ctx->blockout) { i=ctx->buf_len-ctx->buf_off; if (i > outl) i=outl; TINYCLR_SSL_MEMCPY(out,&(ctx->buf[ctx->buf_off]),i); ret+=i; out+=i; outl-=i; ctx->buf_off+=i; /* all clean bytes are out */ if (ctx->buf_len == ctx->buf_off) { ctx->buf_off=0; /* copy start of the next block into proper place */ if(ctx->buf_len_save- ctx->buf_off_save > 0) { ctx->buf_len= ctx->buf_len_save- ctx->buf_off_save; TINYCLR_SSL_MEMMOVE(ctx->buf, &(ctx->buf[ctx->buf_off_save]), ctx->buf_len); } else { ctx->buf_len=0; } ctx->blockout= 0; } } /* output buffer full -- cancel */ if (outl == 0) break; /* no clean bytes in buffer -- fill it */ n=IOBS- ctx->buf_len; i=BIO_read(b->next_bio,&(ctx->buf[ctx->buf_len]),n); if (i <= 0) break; /* nothing new */ ctx->buf_len+= i; /* no signature yet -- check if we got one */ if (ctx->sigio == 1) sig_in(b); /* signature ok -- check if we got block */ if (ctx->sigio == 0) block_in(b); /* invalid block -- cancel */ if (ctx->cont <= 0) break; } BIO_clear_retry_flags(b); BIO_copy_next_retry(b); return(ret); }
static int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size) { RdgPacketHeader header; size_t readCount = 0; int readSize; int status; if (!rdg->packetRemainingCount) { while (readCount < sizeof(RdgPacketHeader)) { status = BIO_read(rdg->tlsOut->bio, (BYTE*)(&header) + readCount, sizeof(RdgPacketHeader) - readCount); if (status <= 0) { if (!BIO_should_retry(rdg->tlsOut->bio)) return -1; if (!readCount) return 0; BIO_wait_read(rdg->tlsOut->bio, 50); continue; } readCount += status; } if (header.type != PKT_TYPE_DATA) { status = rdg_process_control_packet(rdg, header.type, header.packetLength); if (!status) return -1; return 0; } readCount = 0; while (readCount < 2) { status = BIO_read(rdg->tlsOut->bio, (BYTE*)(&rdg->packetRemainingCount) + readCount, 2 - readCount); if (status < 0) { if (!BIO_should_retry(rdg->tlsOut->bio)) return -1; BIO_wait_read(rdg->tlsOut->bio, 50); continue; } readCount += status; } } readSize = (rdg->packetRemainingCount < size ? rdg->packetRemainingCount : size); status = BIO_read(rdg->tlsOut->bio, buffer, readSize); if (status <= 0) { if (!BIO_should_retry(rdg->tlsOut->bio)) { return -1; } return 0; } rdg->packetRemainingCount -= status; return status; }
int DTLSv1_listen(SSL *s, BIO_ADDR *client) { int next, n, ret = 0, clearpkt = 0; unsigned char cookie[DTLS1_COOKIE_LENGTH]; unsigned char seq[SEQ_NUM_SIZE]; const unsigned char *data; unsigned char *buf; size_t fragoff, fraglen, msglen; unsigned int rectype, versmajor, msgseq, msgtype, clientvers, cookielen; BIO *rbio, *wbio; BUF_MEM *bufm; BIO_ADDR *tmpclient = NULL; PACKET pkt, msgpkt, msgpayload, session, cookiepkt; /* Ensure there is no state left over from a previous invocation */ if (!SSL_clear(s)) return -1; ERR_clear_error(); rbio = SSL_get_rbio(s); wbio = SSL_get_wbio(s); if (!rbio || !wbio) { SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_BIO_NOT_SET); return -1; } /* * We only peek at incoming ClientHello's until we're sure we are going to * to respond with a HelloVerifyRequest. If its a ClientHello with a valid * cookie then we leave it in the BIO for accept to handle. */ BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 1, NULL); /* * Note: This check deliberately excludes DTLS1_BAD_VER because that version * requires the MAC to be calculated *including* the first ClientHello * (without the cookie). Since DTLSv1_listen is stateless that cannot be * supported. DTLS1_BAD_VER must use cookies in a stateful manner (e.g. via * SSL_accept) */ if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00)) { SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNSUPPORTED_SSL_VERSION); return -1; } if (s->init_buf == NULL) { if ((bufm = BUF_MEM_new()) == NULL) { SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE); return -1; } if (!BUF_MEM_grow(bufm, SSL3_RT_MAX_PLAIN_LENGTH)) { BUF_MEM_free(bufm); SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE); return -1; } s->init_buf = bufm; } buf = (unsigned char *)s->init_buf->data; do { /* Get a packet */ clear_sys_error(); /* * Technically a ClientHello could be SSL3_RT_MAX_PLAIN_LENGTH * + DTLS1_RT_HEADER_LENGTH bytes long. Normally init_buf does not store * the record header as well, but we do here. We've set up init_buf to * be the standard size for simplicity. In practice we shouldn't ever * receive a ClientHello as long as this. If we do it will get dropped * in the record length check below. */ n = BIO_read(rbio, buf, SSL3_RT_MAX_PLAIN_LENGTH); if (n <= 0) { if (BIO_should_retry(rbio)) { /* Non-blocking IO */ goto end; } return -1; } /* If we hit any problems we need to clear this packet from the BIO */ clearpkt = 1; if (!PACKET_buf_init(&pkt, buf, n)) { SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_INTERNAL_ERROR); return -1; } /* * Parse the received record. If there are any problems with it we just * dump it - with no alert. RFC6347 says this "Unlike TLS, DTLS is * resilient in the face of invalid records (e.g., invalid formatting, * length, MAC, etc.). In general, invalid records SHOULD be silently * discarded, thus preserving the association; however, an error MAY be * logged for diagnostic purposes." */ /* this packet contained a partial record, dump it */ if (n < DTLS1_RT_HEADER_LENGTH) { SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_RECORD_TOO_SMALL); goto end; } if (s->msg_callback) s->msg_callback(0, 0, SSL3_RT_HEADER, buf, DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg); /* Get the record header */ if (!PACKET_get_1(&pkt, &rectype) || !PACKET_get_1(&pkt, &versmajor)) { SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH); goto end; } if (rectype != SSL3_RT_HANDSHAKE) { SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE); goto end; } /* * Check record version number. We only check that the major version is * the same. */ if (versmajor != DTLS1_VERSION_MAJOR) { SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_BAD_PROTOCOL_VERSION_NUMBER); goto end; } if (!PACKET_forward(&pkt, 1) /* Save the sequence number: 64 bits, with top 2 bytes = epoch */ || !PACKET_copy_bytes(&pkt, seq, SEQ_NUM_SIZE) || !PACKET_get_length_prefixed_2(&pkt, &msgpkt)) { SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH); goto end; } /* * We allow data remaining at the end of the packet because there could * be a second record (but we ignore it) */ /* This is an initial ClientHello so the epoch has to be 0 */ if (seq[0] != 0 || seq[1] != 0) { SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE); goto end; } /* Get a pointer to the raw message for the later callback */ data = PACKET_data(&msgpkt); /* Finished processing the record header, now process the message */ if (!PACKET_get_1(&msgpkt, &msgtype) || !PACKET_get_net_3_len(&msgpkt, &msglen) || !PACKET_get_net_2(&msgpkt, &msgseq) || !PACKET_get_net_3_len(&msgpkt, &fragoff) || !PACKET_get_net_3_len(&msgpkt, &fraglen) || !PACKET_get_sub_packet(&msgpkt, &msgpayload, fraglen) || PACKET_remaining(&msgpkt) != 0) { SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH); goto end; } if (msgtype != SSL3_MT_CLIENT_HELLO) { SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE); goto end; } /* Message sequence number can only be 0 or 1 */ if (msgseq > 2) { SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_INVALID_SEQUENCE_NUMBER); goto end; } /* * We don't support fragment reassembly for ClientHellos whilst * listening because that would require server side state (which is * against the whole point of the ClientHello/HelloVerifyRequest * mechanism). Instead we only look at the first ClientHello fragment * and require that the cookie must be contained within it. */ if (fragoff != 0 || fraglen > msglen) { /* Non initial ClientHello fragment (or bad fragment) */ SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_FRAGMENTED_CLIENT_HELLO); goto end; } if (s->msg_callback) s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, data, fraglen + DTLS1_HM_HEADER_LENGTH, s, s->msg_callback_arg); if (!PACKET_get_net_2(&msgpayload, &clientvers)) { SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH); goto end; } /* * Verify client version is supported */ if (DTLS_VERSION_LT(clientvers, (unsigned int)s->method->version) && s->method->version != DTLS_ANY_VERSION) { SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_WRONG_VERSION_NUMBER); goto end; } if (!PACKET_forward(&msgpayload, SSL3_RANDOM_SIZE) || !PACKET_get_length_prefixed_1(&msgpayload, &session) || !PACKET_get_length_prefixed_1(&msgpayload, &cookiepkt)) { /* * Could be malformed or the cookie does not fit within the initial * ClientHello fragment. Either way we can't handle it. */ SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH); goto end; } /* * Check if we have a cookie or not. If not we need to send a * HelloVerifyRequest. */ if (PACKET_remaining(&cookiepkt) == 0) { next = LISTEN_SEND_VERIFY_REQUEST; } else { /* * We have a cookie, so lets check it. */ if (s->ctx->app_verify_cookie_cb == NULL) { SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_NO_VERIFY_COOKIE_CALLBACK); /* This is fatal */ return -1; } if (s->ctx->app_verify_cookie_cb(s, PACKET_data(&cookiepkt), (unsigned int)PACKET_remaining(&cookiepkt)) == 0) { /* * We treat invalid cookies in the same was as no cookie as * per RFC6347 */ next = LISTEN_SEND_VERIFY_REQUEST; } else { /* Cookie verification succeeded */ next = LISTEN_SUCCESS; } } if (next == LISTEN_SEND_VERIFY_REQUEST) { WPACKET wpkt; unsigned int version; size_t wreclen; /* * There was no cookie in the ClientHello so we need to send a * HelloVerifyRequest. If this fails we do not worry about trying * to resend, we just drop it. */ /* * Dump the read packet, we don't need it any more. Ignore return * value */ BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 0, NULL); BIO_read(rbio, buf, SSL3_RT_MAX_PLAIN_LENGTH); BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 1, NULL); /* Generate the cookie */ if (s->ctx->app_gen_cookie_cb == NULL || s->ctx->app_gen_cookie_cb(s, cookie, &cookielen) == 0 || cookielen > 255) { SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_COOKIE_GEN_CALLBACK_FAILURE); /* This is fatal */ return -1; } /* * Special case: for hello verify request, client version 1.0 and we * haven't decided which version to use yet send back using version * 1.0 header: otherwise some clients will ignore it. */ version = (s->method->version == DTLS_ANY_VERSION) ? DTLS1_VERSION : s->version; /* Construct the record and message headers */ if (!WPACKET_init(&wpkt, s->init_buf) || !WPACKET_put_bytes_u8(&wpkt, SSL3_RT_HANDSHAKE) || !WPACKET_put_bytes_u16(&wpkt, version) /* * Record sequence number is always the same as in the * received ClientHello */ || !WPACKET_memcpy(&wpkt, seq, SEQ_NUM_SIZE) /* End of record, start sub packet for message */ || !WPACKET_start_sub_packet_u16(&wpkt) /* Message type */ || !WPACKET_put_bytes_u8(&wpkt, DTLS1_MT_HELLO_VERIFY_REQUEST) /* * Message length - doesn't follow normal TLS convention: * the length isn't the last thing in the message header. * We'll need to fill this in later when we know the * length. Set it to zero for now */ || !WPACKET_put_bytes_u24(&wpkt, 0) /* * Message sequence number is always 0 for a * HelloVerifyRequest */ || !WPACKET_put_bytes_u16(&wpkt, 0) /* * We never fragment a HelloVerifyRequest, so fragment * offset is 0 */ || !WPACKET_put_bytes_u24(&wpkt, 0) /* * Fragment length is the same as message length, but * this *is* the last thing in the message header so we * can just start a sub-packet. No need to come back * later for this one. */ || !WPACKET_start_sub_packet_u24(&wpkt) /* Create the actual HelloVerifyRequest body */ || !dtls_raw_hello_verify_request(&wpkt, cookie, cookielen) /* Close message body */ || !WPACKET_close(&wpkt) /* Close record body */ || !WPACKET_close(&wpkt) || !WPACKET_get_total_written(&wpkt, &wreclen) || !WPACKET_finish(&wpkt)) { SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_INTERNAL_ERROR); WPACKET_cleanup(&wpkt); /* This is fatal */ return -1; } /* * Fix up the message len in the message header. Its the same as the * fragment len which has been filled in by WPACKET, so just copy * that. Destination for the message len is after the record header * plus one byte for the message content type. The source is the * last 3 bytes of the message header */ memcpy(&buf[DTLS1_RT_HEADER_LENGTH + 1], &buf[DTLS1_RT_HEADER_LENGTH + DTLS1_HM_HEADER_LENGTH - 3], 3); if (s->msg_callback) s->msg_callback(1, 0, SSL3_RT_HEADER, buf, DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg); if ((tmpclient = BIO_ADDR_new()) == NULL) { SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE); goto end; } /* * This is unnecessary if rbio and wbio are one and the same - but * maybe they're not. We ignore errors here - some BIOs do not * support this. */ if (BIO_dgram_get_peer(rbio, tmpclient) > 0) { (void)BIO_dgram_set_peer(wbio, tmpclient); } BIO_ADDR_free(tmpclient); tmpclient = NULL; /* TODO(size_t): convert this call */ if (BIO_write(wbio, buf, wreclen) < (int)wreclen) { if (BIO_should_retry(wbio)) { /* * Non-blocking IO...but we're stateless, so we're just * going to drop this packet. */ goto end; } return -1; } if (BIO_flush(wbio) <= 0) { if (BIO_should_retry(wbio)) { /* * Non-blocking IO...but we're stateless, so we're just * going to drop this packet. */ goto end; } return -1; } } } while (next != LISTEN_SUCCESS); /* * Set expected sequence numbers to continue the handshake. */ s->d1->handshake_read_seq = 1; s->d1->handshake_write_seq = 1; s->d1->next_handshake_write_seq = 1; DTLS_RECORD_LAYER_set_write_sequence(&s->rlayer, seq); /* * We are doing cookie exchange, so make sure we set that option in the * SSL object */ SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE); /* * Tell the state machine that we've done the initial hello verify * exchange */ ossl_statem_set_hello_verify_done(s); /* * Some BIOs may not support this. If we fail we clear the client address */ if (BIO_dgram_get_peer(rbio, client) <= 0) BIO_ADDR_clear(client); ret = 1; clearpkt = 0; end: BIO_ADDR_free(tmpclient); BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 0, NULL); if (clearpkt) { /* Dump this packet. Ignore return value */ BIO_read(rbio, buf, SSL3_RT_MAX_PLAIN_LENGTH); } return ret; }
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) { BUF_MEM *b; unsigned char *p; int i; size_t want = HEADER_SIZE; int eos = 0; size_t off = 0; size_t len = 0; const unsigned char *q; long slen; int inf, tag, xclass; b = BUF_MEM_new(); if (b == NULL) { ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); return -1; } ERR_clear_error(); for (;;) { if (want >= (len - off)) { want -= (len - off); if (len + want < len || !BUF_MEM_grow_clean(b, len + want)) { ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); goto err; } i = BIO_read(in, &(b->data[len]), want); if ((i < 0) && ((len - off) == 0)) { ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_NOT_ENOUGH_DATA); goto err; } if (i > 0) { if (len + i < len) { ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); goto err; } len += i; } } /* else data already loaded */ p = (unsigned char *)&(b->data[off]); q = p; inf = ASN1_get_object(&q, &slen, &tag, &xclass, len - off); if (inf & 0x80) { unsigned long e; e = ERR_GET_REASON(ERR_peek_error()); if (e != ASN1_R_TOO_LONG) goto err; else ERR_clear_error(); /* clear error */ } i = q - p; /* header length */ off += i; /* end of data */ if (inf & 1) { /* no data body so go round again */ eos++; if (eos < 0) { ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_HEADER_TOO_LONG); goto err; } want = HEADER_SIZE; } else if (eos && (slen == 0) && (tag == V_ASN1_EOC)) { /* eos value, so go back and read another header */ eos--; if (eos <= 0) break; else want = HEADER_SIZE; } else { /* suck in slen bytes of data */ want = slen; if (want > (len - off)) { want -= (len - off); if (want > INT_MAX /* BIO_read takes an int length */ || len + want < len) { ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); goto err; } if (!BUF_MEM_grow_clean(b, len + want)) { ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); goto err; } while (want > 0) { i = BIO_read(in, &(b->data[len]), want); if (i <= 0) { ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_NOT_ENOUGH_DATA); goto err; } /* * This can't overflow because |len+want| didn't * overflow. */ len += i; want -= i; } } if (off + slen < off) { ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); goto err; } off += slen; if (eos <= 0) { break; } else want = HEADER_SIZE; } } if (off > INT_MAX) { ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); goto err; } *pb = b; return off; err: if (b != NULL) BUF_MEM_free(b); return -1; }
//-------------------------------------------------- // sends an OCSP_REQUES object to remore server and // retrieves the OCSP_RESPONSE object // resp - buffer to store the new responses pointer // req - request objects pointer // url - OCSP responder URL //-------------------------------------------------- int ddocPullUrl(const char* url, DigiDocMemBuf* pSendData, DigiDocMemBuf* pRecvData, const char* proxyHost, const char* proxyPort) { BIO* cbio = 0, *sbio = 0; SSL_CTX *ctx = NULL; char *host = NULL, *port = NULL, *path = "/", buf[200]; int err = ERR_OK, use_ssl = -1, rc; long e; //RETURN_IF_NULL_PARAM(pSendData); // may be null if nothing to send? RETURN_IF_NULL_PARAM(pRecvData); RETURN_IF_NULL_PARAM(url); ddocDebug(4, "ddocPullUrl", "URL: %s, in: %d bytes", url, pSendData->nLen); //there is an HTTP proxy - connect to that instead of the target host if (proxyHost != 0 && *proxyHost != '\0') { host = (char*)proxyHost; if(proxyPort != 0 && *proxyPort != '\0') port = (char*)proxyPort; path = (char*)url; } else { if(OCSP_parse_url((char*)url, &host, &port, &path, &use_ssl) == 0) { ddocDebug(1, "ddocPullUrl", "Failed to parse the URL"); return ERR_WRONG_URL_OR_PROXY; } } if((cbio = BIO_new_connect(host)) != 0) { ddocDebug(4, "ddocPullUrl", "Host: %s port: %s", host, port); if(port != NULL) { BIO_set_conn_port(cbio, port); } if(use_ssl == 1) { ctx = SSL_CTX_new(SSLv23_client_method()); SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); sbio = BIO_new_ssl(ctx, 1); cbio = BIO_push(sbio, cbio); } if ((rc = BIO_do_connect(cbio)) > 0) { ddocDebug(4, "ddocPullUrl", "Connected: %d", rc); if(pSendData && pSendData->nLen && pSendData->pMem) { rc = BIO_write(cbio, pSendData->pMem, pSendData->nLen); ddocDebug(4, "ddocPullUrl", "Sent: %d bytes, got: %d", pSendData->nLen, rc); } do { memset(buf, 0, sizeof(buf)); rc = BIO_read(cbio, buf, sizeof(buf)-1); ddocDebug(4, "ddocPullUrl", "Received: %d bytes\n", rc); if(rc > 0) err = ddocMemAppendData(pRecvData, buf, rc); } while(rc > 0); ddocDebug(4, "ddocPullUrl", "Total received: %d bytes\n", pRecvData->nLen); } else { //if no connection e = checkErrors(); if(ERR_GET_REASON(e) == BIO_R_BAD_HOSTNAME_LOOKUP || ERR_GET_REASON(e) == OCSP_R_SERVER_WRITE_ERROR) err = ERR_CONNECTION_FAILURE; else err = (host != NULL) ? ERR_WRONG_URL_OR_PROXY : ERR_CONNECTION_FAILURE; } BIO_free_all(cbio); if (use_ssl != -1) { OPENSSL_free(host); OPENSSL_free(port); OPENSSL_free(path); SSL_CTX_free(ctx); } } else err = ERR_CONNECTION_FAILURE; return(err); }
int doit (io_channel chan, SSL_CTX * s_ctx) { int status, length, link_state; struct rpc_msg msg; SSL *s_ssl = NULL; BIO *c_to_s = NULL; BIO *s_to_c = NULL; BIO *c_bio = NULL; BIO *s_bio = NULL; int i; int done = 0; s_ssl = SSL_new (s_ctx); if (s_ssl == NULL) goto err; c_to_s = BIO_new (BIO_s_rtcp ()); s_to_c = BIO_new (BIO_s_rtcp ()); if ((s_to_c == NULL) || (c_to_s == NULL)) goto err; /* original, DRM 24-SEP-1997 BIO_set_fd ( c_to_s, "", chan ); BIO_set_fd ( s_to_c, "", chan ); */ BIO_set_fd (c_to_s, 0, chan); BIO_set_fd (s_to_c, 0, chan); c_bio = BIO_new (BIO_f_ssl ()); s_bio = BIO_new (BIO_f_ssl ()); if ((c_bio == NULL) || (s_bio == NULL)) goto err; SSL_set_accept_state (s_ssl); SSL_set_bio (s_ssl, c_to_s, s_to_c); BIO_set_ssl (s_bio, s_ssl, BIO_CLOSE); /* We can always do writes */ printf ("Begin doit main loop\n"); /* * Link states: 0-idle, 1-read pending, 2-write pending, 3-closed. */ for (link_state = 0; link_state < 3;) { /* * Wait for remote end to request data action on A channel. */ while (link_state == 0) { status = get (chan, (char *) &msg, sizeof (msg), &length); if ((status & 1) == 0) { printf ("Error in main loop get: %d\n", status); link_state = 3; break; } if (length < RPC_HDR_SIZE) { printf ("Error in main loop get size: %d\n", length); break; link_state = 3; } if (msg.channel != 'A') { printf ("Error in main loop, unexpected channel: %c\n", msg.channel); break; link_state = 3; } if (msg.function == 'G') { link_state = 1; } else if (msg.function == 'P') { link_state = 2; /* write pending */ } else if (msg.function == 'X') { link_state = 3; } else { link_state = 3; } } if (link_state == 1) { i = BIO_read (s_bio, msg.data, msg.length); if (i < 0) link_state = 3; else { msg.channel = 'A'; msg.function = 'C'; /* confirm */ msg.length = i; status = put (chan, (char *) &msg, i + RPC_HDR_SIZE); if ((status & 1) == 0) break; link_state = 0; } } else if (link_state == 2) { i = BIO_write (s_bio, msg.data, msg.length); if (i < 0) link_state = 3; else { msg.channel = 'A'; msg.function = 'C'; /* confirm */ msg.length = 0; status = put (chan, (char *) &msg, RPC_HDR_SIZE); if ((status & 1) == 0) break; link_state = 0; } } } fprintf (stdout, "DONE\n"); err: /* We have to set the BIO's to NULL otherwise they will be * free()ed twice. Once when th s_ssl is SSL_free()ed and * again when c_ssl is SSL_free()ed. * This is a hack required because s_ssl and c_ssl are sharing the same * BIO structure and SSL_set_bio() and SSL_free() automatically * BIO_free non NULL entries. * You should not normally do this or be required to do this */ s_ssl->rbio = NULL; s_ssl->wbio = NULL; if (c_to_s != NULL) BIO_free (c_to_s); if (s_to_c != NULL) BIO_free (s_to_c); if (c_bio != NULL) BIO_free (c_bio); if (s_bio != NULL) BIO_free (s_bio); return (0); }
int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, EVP_PKEY *key, unsigned char *sigin, int siglen, const char *title, const char *file) { int len; int i; for (;;) { i=BIO_read(bp,(char *)buf,BUFSIZE); if(i < 0) { BIO_printf(bio_err, "Read Error in %s\n",file); ERR_print_errors(bio_err); return 1; } if (i == 0) break; } if(sigin) { EVP_MD_CTX *ctx; BIO_get_md_ctx(bp, &ctx); i = EVP_VerifyFinal(ctx, sigin, (unsigned int)siglen, key); if(i > 0) BIO_printf(out, "Verified OK\n"); else if(i == 0) { BIO_printf(out, "Verification Failure\n"); return 1; } else { BIO_printf(bio_err, "Error Verifying Data\n"); ERR_print_errors(bio_err); return 1; } return 0; } if(key) { EVP_MD_CTX *ctx; BIO_get_md_ctx(bp, &ctx); if(!EVP_SignFinal(ctx, buf, (unsigned int *)&len, key)) { BIO_printf(bio_err, "Error Signing Data\n"); ERR_print_errors(bio_err); return 1; } } else len=BIO_gets(bp,(char *)buf,BUFSIZE); if(binout) BIO_write(out, buf, len); else { BIO_write(out,title,strlen(title)); for (i=0; i<len; i++) { if (sep && (i != 0)) BIO_printf(out, ":"); BIO_printf(out, "%02x",buf[i]); } BIO_printf(out, "\n"); } return 0; }
static int ok_read(BIO *b, char *out, int outl) { int ret = 0, i, n; BIO_OK_CTX *ctx; BIO *next; if (out == NULL) return 0; ctx = BIO_get_data(b); next = BIO_next(b); if ((ctx == NULL) || (next == NULL) || (BIO_get_init(b) == 0)) return 0; while (outl > 0) { /* copy clean bytes to output buffer */ if (ctx->blockout) { i = ctx->buf_len - ctx->buf_off; if (i > outl) i = outl; memcpy(out, &(ctx->buf[ctx->buf_off]), i); ret += i; out += i; outl -= i; ctx->buf_off += i; /* all clean bytes are out */ if (ctx->buf_len == ctx->buf_off) { ctx->buf_off = 0; /* * copy start of the next block into proper place */ if (ctx->buf_len_save - ctx->buf_off_save > 0) { ctx->buf_len = ctx->buf_len_save - ctx->buf_off_save; memmove(ctx->buf, &(ctx->buf[ctx->buf_off_save]), ctx->buf_len); } else { ctx->buf_len = 0; } ctx->blockout = 0; } } /* output buffer full -- cancel */ if (outl == 0) break; /* no clean bytes in buffer -- fill it */ n = IOBS - ctx->buf_len; i = BIO_read(next, &(ctx->buf[ctx->buf_len]), n); if (i <= 0) break; /* nothing new */ ctx->buf_len += i; /* no signature yet -- check if we got one */ if (ctx->sigio == 1) { if (!sig_in(b)) { BIO_clear_retry_flags(b); return 0; } } /* signature ok -- check if we got block */ if (ctx->sigio == 0) { if (!block_in(b)) { BIO_clear_retry_flags(b); return 0; } } /* invalid block -- cancel */ if (ctx->cont <= 0) break; } BIO_clear_retry_flags(b); BIO_copy_next_retry(b); return ret; }
int MAIN(int argc, char **argv) { ENGINE *e = NULL; unsigned char *buf=NULL; int i,err=0; const EVP_MD *md=NULL,*m; BIO *in=NULL,*inp; BIO *bmd=NULL; BIO *out = NULL; const char *name; #define PROG_NAME_SIZE 39 char pname[PROG_NAME_SIZE+1]; int separator=0; int debug=0; int keyform=FORMAT_PEM; const char *outfile = NULL, *keyfile = NULL; const char *sigfile = NULL, *randfile = NULL; int out_bin = -1, want_pub = 0, do_verify = 0; EVP_PKEY *sigkey = NULL; unsigned char *sigbuf = NULL; int siglen = 0; char *passargin = NULL, *passin = NULL; #ifndef OPENSSL_NO_ENGINE char *engine=NULL; #endif apps_startup(); if ((buf=(unsigned char *)OPENSSL_malloc(BUFSIZE)) == NULL) { BIO_printf(bio_err,"out of memory\n"); goto end; } if (bio_err == NULL) if ((bio_err=BIO_new(BIO_s_file())) != NULL) BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); if (!load_config(bio_err, NULL)) goto end; /* first check the program name */ program_name(argv[0],pname,sizeof pname); md=EVP_get_digestbyname(pname); argc--; argv++; while (argc > 0) { if ((*argv)[0] != '-') break; if (strcmp(*argv,"-c") == 0) separator=1; else if (strcmp(*argv,"-rand") == 0) { if (--argc < 1) break; randfile=*(++argv); } else if (strcmp(*argv,"-out") == 0) { if (--argc < 1) break; outfile=*(++argv); } else if (strcmp(*argv,"-sign") == 0) { if (--argc < 1) break; keyfile=*(++argv); } else if (!strcmp(*argv,"-passin")) { if (--argc < 1) break; passargin=*++argv; } else if (strcmp(*argv,"-verify") == 0) { if (--argc < 1) break; keyfile=*(++argv); want_pub = 1; do_verify = 1; } else if (strcmp(*argv,"-prverify") == 0) { if (--argc < 1) break; keyfile=*(++argv); do_verify = 1; } else if (strcmp(*argv,"-signature") == 0) { if (--argc < 1) break; sigfile=*(++argv); } else if (strcmp(*argv,"-keyform") == 0) { if (--argc < 1) break; keyform=str2fmt(*(++argv)); } #ifndef OPENSSL_NO_ENGINE else if (strcmp(*argv,"-engine") == 0) { if (--argc < 1) break; engine= *(++argv); } #endif else if (strcmp(*argv,"-hex") == 0) out_bin = 0; else if (strcmp(*argv,"-binary") == 0) out_bin = 1; else if (strcmp(*argv,"-d") == 0) debug=1; else if ((m=EVP_get_digestbyname(&((*argv)[1]))) != NULL) md=m; else break; argc--; argv++; } if (md == NULL) md=EVP_md5(); if(do_verify && !sigfile) { BIO_printf(bio_err, "No signature to verify: use the -signature option\n"); err = 1; goto end; } if ((argc > 0) && (argv[0][0] == '-')) /* bad option */ { BIO_printf(bio_err,"unknown option '%s'\n",*argv); BIO_printf(bio_err,"options are\n"); BIO_printf(bio_err,"-c to output the digest with separating colons\n"); BIO_printf(bio_err,"-d to output debug info\n"); BIO_printf(bio_err,"-hex output as hex dump\n"); BIO_printf(bio_err,"-binary output in binary form\n"); BIO_printf(bio_err,"-sign file sign digest using private key in file\n"); BIO_printf(bio_err,"-verify file verify a signature using public key in file\n"); BIO_printf(bio_err,"-prverify file verify a signature using private key in file\n"); BIO_printf(bio_err,"-keyform arg key file format (PEM or ENGINE)\n"); BIO_printf(bio_err,"-signature file signature to verify\n"); BIO_printf(bio_err,"-binary output in binary form\n"); #ifndef OPENSSL_NO_ENGINE BIO_printf(bio_err,"-engine e use engine e, possibly a hardware device.\n"); #endif BIO_printf(bio_err,"-%3s to use the %s message digest algorithm (default)\n", LN_md5,LN_md5); BIO_printf(bio_err,"-%3s to use the %s message digest algorithm\n", LN_md4,LN_md4); BIO_printf(bio_err,"-%3s to use the %s message digest algorithm\n", LN_md2,LN_md2); #ifndef OPENSSL_NO_SHA BIO_printf(bio_err,"-%3s to use the %s message digest algorithm\n", LN_sha1,LN_sha1); BIO_printf(bio_err,"-%3s to use the %s message digest algorithm\n", LN_sha,LN_sha); #ifndef OPENSSL_NO_SHA256 BIO_printf(bio_err,"-%3s to use the %s message digest algorithm\n", LN_sha256,LN_sha256); #endif #ifndef OPENSSL_NO_SHA512 BIO_printf(bio_err,"-%3s to use the %s message digest algorithm\n", LN_sha512,LN_sha512); #endif #endif BIO_printf(bio_err,"-%3s to use the %s message digest algorithm\n", LN_mdc2,LN_mdc2); BIO_printf(bio_err,"-%3s to use the %s message digest algorithm\n", LN_ripemd160,LN_ripemd160); err=1; goto end; } #ifndef OPENSSL_NO_ENGINE e = setup_engine(bio_err, engine, 0); #endif in=BIO_new(BIO_s_file()); bmd=BIO_new(BIO_f_md()); if (debug) { BIO_set_callback(in,BIO_debug_callback); /* needed for windows 3.1 */ BIO_set_callback_arg(in,(char *)bio_err); } if(!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } if ((in == NULL) || (bmd == NULL)) { ERR_print_errors(bio_err); goto end; } if(out_bin == -1) { if(keyfile) out_bin = 1; else out_bin = 0; } if(randfile) app_RAND_load_file(randfile, bio_err, 0); if(outfile) { if(out_bin) out = BIO_new_file(outfile, "wb"); else out = BIO_new_file(outfile, "w"); } else { out = BIO_new_fp(stdout, BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); out = BIO_push(tmpbio, out); } #endif } if(!out) { BIO_printf(bio_err, "Error opening output file %s\n", outfile ? outfile : "(stdout)"); ERR_print_errors(bio_err); goto end; } if(keyfile) { if (want_pub) sigkey = load_pubkey(bio_err, keyfile, keyform, 0, NULL, e, "key file"); else sigkey = load_key(bio_err, keyfile, keyform, 0, passin, e, "key file"); if (!sigkey) { /* load_[pub]key() has already printed an appropriate message */ goto end; } } if(sigfile && sigkey) { BIO *sigbio; sigbio = BIO_new_file(sigfile, "rb"); siglen = EVP_PKEY_size(sigkey); sigbuf = OPENSSL_malloc(siglen); if(!sigbio) { BIO_printf(bio_err, "Error opening signature file %s\n", sigfile); ERR_print_errors(bio_err); goto end; } siglen = BIO_read(sigbio, sigbuf, siglen); BIO_free(sigbio); if(siglen <= 0) { BIO_printf(bio_err, "Error reading signature file %s\n", sigfile); ERR_print_errors(bio_err); goto end; } } /* we use md as a filter, reading from 'in' */ if (!BIO_set_md(bmd,md)) { BIO_printf(bio_err, "Error setting digest %s\n", pname); ERR_print_errors(bio_err); goto end; } inp=BIO_push(bmd,in); if (argc == 0) { BIO_set_fp(in,stdin,BIO_NOCLOSE); err=do_fp(out, buf,inp,separator, out_bin, sigkey, sigbuf, siglen,"","(stdin)"); } else { name=OBJ_nid2sn(md->type); for (i=0; i<argc; i++) { char *tmp,*tofree=NULL; int r; if (BIO_read_filename(in,argv[i]) <= 0) { perror(argv[i]); err++; continue; } if(!out_bin) { size_t len = strlen(name)+strlen(argv[i])+5; tmp=tofree=OPENSSL_malloc(len); BIO_snprintf(tmp,len,"%s(%s)= ",name,argv[i]); } else tmp=""; r=do_fp(out,buf,inp,separator,out_bin,sigkey,sigbuf, siglen,tmp,argv[i]); if(r) err=r; if(tofree) OPENSSL_free(tofree); (void)BIO_reset(bmd); } } end: if (buf != NULL) { OPENSSL_cleanse(buf,BUFSIZE); OPENSSL_free(buf); } if (in != NULL) BIO_free(in); if (passin) OPENSSL_free(passin); BIO_free_all(out); EVP_PKEY_free(sigkey); if(sigbuf) OPENSSL_free(sigbuf); if (bmd != NULL) BIO_free(bmd); apps_shutdown(); OPENSSL_EXIT(err); }
static int pk7_verify(X509_STORE *cert_store, PKCS7 *p7, BIO *detached, char *ebuf, int ebufsize) { PKCS7_SIGNER_INFO *si; verify_context vctx; BIO *p7bio=NULL; char readbuf[1024*4]; int res = 1; int i; STACK_OF(PKCS7_SIGNER_INFO) *sk; vctx.err = X509_V_OK; ebuf[0] = 0; OpenSSL_add_all_algorithms(); EVP_add_digest(EVP_md5()); EVP_add_digest(EVP_sha1()); ERR_load_crypto_strings(); ERR_clear_error(); X509_VERIFY_PARAM_set_flags(cert_store->param, X509_V_FLAG_CB_ISSUER_CHECK); X509_STORE_set_verify_cb_func(cert_store, verify_callback); p7bio = PKCS7_dataInit(p7, detached); /* We now have to 'read' from p7bio to calculate digests etc. */ while (BIO_read(p7bio, readbuf, sizeof(readbuf)) > 0) ; /* We can now verify signatures */ sk = PKCS7_get_signer_info(p7); if (sk == NULL) { /* there are no signatures on this data */ res = 0; fz_strlcpy(ebuf, "No signatures", ebufsize); goto exit; } for (i=0; i<sk_PKCS7_SIGNER_INFO_num(sk); i++) { int rc; si = sk_PKCS7_SIGNER_INFO_value(sk, i); rc = PKCS7_dataVerify(cert_store, &vctx.x509_ctx, p7bio,p7, si); if (rc <= 0 || vctx.err != X509_V_OK) { char tbuf[120]; if (rc <= 0) { fz_strlcpy(ebuf, ERR_error_string(ERR_get_error(), tbuf), ebufsize); } else { /* Error while checking the certificate chain */ snprintf(ebuf, ebufsize, "%s(%d): %s", X509_verify_cert_error_string(vctx.err), vctx.err, vctx.certdesc); } res = 0; goto exit; } } exit: X509_STORE_CTX_cleanup(&vctx.x509_ctx); ERR_free_strings(); return res; }
static int buffer_read(BIO *b, char *out, int outl) { int i, num = 0; BIO_F_BUFFER_CTX *ctx; if (out == NULL) return 0; ctx = (BIO_F_BUFFER_CTX *)b->ptr; if ((ctx == NULL) || (b->next_bio == NULL)) return 0; num = 0; BIO_clear_retry_flags(b); start: i = ctx->ibuf_len; /* If there is stuff left over, grab it */ if (i != 0) { if (i > outl) i = outl; memcpy(out, &(ctx->ibuf[ctx->ibuf_off]), i); ctx->ibuf_off += i; ctx->ibuf_len -= i; num += i; if (outl == i) return num; outl -= i; out += i; } /* * We may have done a partial read. try to do more. We have nothing in * the buffer. If we get an error and have read some data, just return it * and let them retry to get the error again. copy direct to parent * address space */ if (outl > ctx->ibuf_size) { for (;;) { i = BIO_read(b->next_bio, out, outl); if (i <= 0) { BIO_copy_next_retry(b); if (i < 0) return ((num > 0) ? num : i); if (i == 0) return num; } num += i; if (outl == i) return num; out += i; outl -= i; } } /* else */ /* we are going to be doing some buffering */ i = BIO_read(b->next_bio, ctx->ibuf, ctx->ibuf_size); if (i <= 0) { BIO_copy_next_retry(b); if (i < 0) return ((num > 0) ? num : i); if (i == 0) return num; } ctx->ibuf_off = 0; ctx->ibuf_len = i; /* Lets re-read using ourselves :-) */ goto start; }
void ServiceTask::run() { //logger << dlib << endl; string ip = "invalid session"; string alldatlg = "\ngot fd from parent"; SSL *ssl=NULL; BIO *sbio=NULL; BIO *io=NULL,*ssl_bio=NULL; try { int cntlen = 0; char buf[MAXBUFLENM]; strVec results; stringstream ss; string temp; //int bytes = -1; if(isSSLEnabled) { sbio=BIO_new_socket(fd,BIO_NOCLOSE); ssl=SSL_new(ctx); SSL_set_bio(ssl,sbio,sbio); io=BIO_new(BIO_f_buffer()); ssl_bio=BIO_new(BIO_f_ssl()); BIO_set_ssl(ssl_bio,ssl,BIO_CLOSE); BIO_push(io,ssl_bio); int r = SSL_accept(ssl); cout << r << endl; int bser = SSL_get_error(ssl,r); cout << bser << endl; if(r<=0) { sslHandler.error_occurred((char*)"SSL accept error",fd,ssl); return; } int er=-1; bool flag = true; while(flag) { er = BIO_gets(io,buf,BUFSIZZ-1); cout << er << endl; int bser = SSL_get_error(ssl,er); cout << bser << endl; switch(bser) { case SSL_ERROR_WANT_READ: { logger << "more to read error" << endl; break; } case SSL_ERROR_WANT_WRITE: { logger << "more to write error" << endl; break; } case SSL_ERROR_NONE: { break; } case SSL_ERROR_ZERO_RETURN: { sslHandler.error_occurred((char*)"SSL error problem",fd,ssl); if(io!=NULL)BIO_free(io); return; } default: { sslHandler.error_occurred((char*)"SSL read problem",fd,ssl); if(io!=NULL)BIO_free(io); return; } } ss << buf; //logger <<buf <<endl; if(!strcmp(buf,"\r\n") || !strcmp(buf,"\n")) break; string temp(buf); if(temp=="")continue; temp = temp.substr(0,temp.length()-1); results.push_back(temp); //logger << temp <<endl; if(temp.find("Content-Length:")!=string::npos) { std::string cntle = temp.substr(temp.find(": ")+2); cntle = cntle.substr(0,cntle.length()-1); //logger << "contne-length="<<cntle <<endl; try { cntlen = CastUtil::lexical_cast<int>(cntle); } catch(const char* ex) { logger << "bad lexical cast" <<endl; } } memset(&buf[0], 0, sizeof(buf)); } } else { int er=-1; bool flag = true; sbio=BIO_new_socket(fd,BIO_CLOSE); io=BIO_new(BIO_f_buffer()); BIO_push(io,sbio); logger << "into run method" << endl; while(flag) { er = BIO_gets(io,buf,BUFSIZZ-1); if(er==0) { close(fd); logger << "\nsocket closed before being serviced" <<flush; return; } ss << buf; if(!strcmp(buf,"\r\n") || !strcmp(buf,"\n") || er<0) break; string temp(buf); temp = temp.substr(0,temp.length()-1); results.push_back(temp); //logger << temp <<endl; if(temp.find("Content-Length:")!=string::npos) { std::string cntle = temp.substr(temp.find(": ")+2); cntle = cntle.substr(0,cntle.length()-1); //logger << "contne-length="<<cntle <<endl; try { cntlen = CastUtil::lexical_cast<int>(cntle); } catch(const char* ex) { logger << "bad lexical cast" <<endl; } } memset(&buf[0], 0, sizeof(buf)); } } ss.clear(); if(isSSLEnabled && cntlen>0) { int er=-1; if(cntlen>0) { //logger << "reading conetnt " << cntlen << endl; er = BIO_read(io,buf,cntlen); switch(SSL_get_error(ssl,er)) { case SSL_ERROR_NONE: cntlen -= er; break; case SSL_ERROR_ZERO_RETURN: { sslHandler.error_occurred((char*)"SSL error problem",fd,ssl); if(io!=NULL)BIO_free(io); return; } default: { sslHandler.error_occurred((char*)"SSL read problem",fd,ssl); if(io!=NULL)BIO_free(io); return; } } string temp(buf); results.push_back("\r"); results.push_back(temp); //logger <<buf <<endl; memset(&buf[0], 0, sizeof(buf)); } } else if(cntlen>0) { int er=-1; if(cntlen>0) { //logger << "reading conetnt " << cntlen << endl; er = BIO_read(io,buf,cntlen); if(er==0) { close(fd); logger << "\nsocket closed before being serviced" <<flush; return; } else if(er>0) { string temp(buf); results.push_back("\r"); results.push_back(temp); //logger << temp <<endl; memset(&buf[0], 0, sizeof(buf)); } } } alldatlg += "--read data"; map<string,string> params1 = *params; string webpath = serverRootDirectory + "web/"; HttpRequest* req= new HttpRequest(results,webpath); //logger << req->toString() << endl; if(req->getFile()=="") { logger << req->getFile() << endl; req->setFile("index.html"); } if(req->hasCookie()) { logger << "has the session id" << endl; if(!configData.sessatserv) req->getSession()->setSessionAttributes(req->getCookieInfo()); else { string id = req->getCookieInfoAttribute("FFEADID"); logger << id << endl; map<string,string> values = readFromSharedMemeory(id); req->getSession()->setSessionAttributes(values); } } if(configData.cntMap[req->getCntxt_name()]!="true") { req->setCntxt_name("default"); req->setCntxt_root(webpath+"default"); req->setUrl(webpath+"default"+req->getActUrl()); } //logger << req->getCntxt_name() << req->getCntxt_root() << req->getUrl() << endl; if(configData.appMap[req->getCntxt_name()]!="false") { if(dlib == NULL) { cerr << dlerror() << endl; exit(-1); } string meth1 = (req->getCntxt_name()+"checkRules"); string path1; void *mkr1 = dlsym(dlib, meth1.c_str()); if(mkr1!=NULL) { typedef string (*DCPPtr1) (string,HttpSession); DCPPtr1 f = (DCPPtr1)mkr1; path1 = f(req->getUrl(),*(req->getSession())); //logger << path1 << flush; if(path1=="FAILED") { req->setUrl(""); } else if(path1!="" && path1!=req->getUrl()) { req->setUrl(path1); } } } HttpResponse res; string ext = getFileExtension(req->getUrl()); vector<unsigned char> test; string content; string claz; bool isoAuthRes = false; long sessionTimeoutVar = configData.sessionTimeout; bool isContrl = securityHandler.handle(configData.ip_address, req, res, configData.securityObjectMap, sessionTimeoutVar, dlib, configData.cntMap); filterHandler.handleIn(req, res, configData.filterMap, dlib, ext); if(!isContrl) { isContrl = authHandler.handle(configData.autMap, configData.autpattMap, req, res, configData.filterMap, dlib, ext); } string pthwofile = req->getCntxt_name()+req->getActUrl(); if(req->getCntxt_name()!="default" && configData.cntMap[req->getCntxt_name()]=="true") { pthwofile = req->getActUrl(); } if(!isContrl) { isContrl = controllerHandler.handle(req, res, configData.urlpattMap, configData.mappattMap, dlib, ext, configData.rstCntMap, configData.mapMap, configData.urlMap, pthwofile); } /*After going through the controller the response might be blank, just set the HTTP version*/ res.setHttpVersion(req->getHttpVersion()); //logger << req->toString() << endl; if(req->getMethod()!="TRACE") { if(isContrl) { } else if(ext==".form") { formHandler.handle(req, res, configData.formMap, dlib); } else if((req->getContent_type().find("application/soap+xml")!=string::npos || req->getContent_type().find("text/xml")!=string::npos) && (req->getContent().find("<soap:Envelope")!=string::npos || req->getContent().find("<soapenv:Envelope")!=string::npos) && configData.wsdlmap[req->getFile()]==req->getCntxt_name()) { soapHandler.handle(req, res, dlib, configData.props[".xml"]); } else { bool cntrlit = scriptHandler.handle(req, res, configData.handoffs, dlib, ext, configData.props); logger << "html page requested" <<endl; if(cntrlit) { } else { cntrlit = extHandler.handle(req, res, dlib, configData.resourcePath, configData.tmplMap, configData.vwMap, ext, configData.props); } if(!cntrlit && ext==".fview") { content = fviewHandler.handle(req, res, configData.fviewmap); } else { if(res.getContent_str()=="") content = getContentStr(req->getUrl(),configData.lprops[req->getDefaultLocale()],ext); else content = res.getContent_str(); } if(content.length()==0) { res.setStatusCode("404"); res.setStatusMsg("Not Found"); //res.setContent_len(CastUtil::lexical_cast<string>(0)); } else { res.setStatusCode("200"); res.setStatusMsg("OK"); if(res.getContent_type()=="")res.setContent_type(configData.props[ext]); res.setContent_str(content); //res.setContent_len(CastUtil::lexical_cast<string>(content.length())); //sess.setAttribute("CURR",req->getUrl()); } } filterHandler.handleOut(req, res, configData.filterMap, dlib, ext); } alldatlg += "--processed data"; string h1; bool sessionchanged = !req->hasCookie(); sessionchanged |= req->getSession()->isDirty(); if(req->getConnection()!="") res.setConnection("close"); createResponse(res,sessionchanged,req->getSession()->getSessionAttributes(),req->getCookieInfoAttribute("FFEADID"), sessionTimeoutVar, configData.sessatserv); //Head should behave exactly as Get but there should be no entity body if(req->getMethod()=="HEAD") { h1 = res.generateHeadResponse(); } else if(req->getMethod()=="OPTIONS") { h1 = res.generateOptionsResponse(); } else if(req->getMethod()=="TRACE") { h1 = res.generateTraceResponse(req); } else { h1 = res.generateResponse(); } //logger << h1 << endl; if(isSSLEnabled) { int r; /* Now perform renegotiation if requested */ if(configData.client_auth==CLIENT_AUTH_REHANDSHAKE){ SSL_set_verify(ssl,SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,0); /* Stop the client from just resuming the un-authenticated session */ SSL_set_session_id_context(ssl, (const unsigned char*)&SSLHandler::s_server_auth_session_id_context, sizeof(SSLHandler::s_server_auth_session_id_context)); if(SSL_renegotiate(ssl)<=0) { sslHandler.error_occurred((char*)"SSL renegotiation error",fd,ssl); if(io!=NULL)BIO_free(io); return; } if(SSL_do_handshake(ssl)<=0) { sslHandler.error_occurred((char*)"SSL renegotiation error",fd,ssl); if(io!=NULL)BIO_free(io); return; } ssl->state=SSL_ST_ACCEPT; if(SSL_do_handshake(ssl)<=0) { sslHandler.error_occurred((char*)"SSL renegotiation error",fd,ssl); if(io!=NULL)BIO_free(io); return; } } if((r=BIO_puts(io,h1.c_str()))<=0) { sslHandler.error_occurred((char*)"send failed",fd,ssl); if(io!=NULL)BIO_free(io); return; } if((r=BIO_flush(io))<0) { sslHandler.error_occurred((char*)"Error flushing BIO",fd,ssl); if(io!=NULL)BIO_free(io); return; } sslHandler.closeSSL(fd,ssl,io); } else { int size; if ((size=send(fd,&h1[0] , h1.length(), 0)) == -1) logger << "send failed" << flush; else if(size==0) { close(fd); memset(&buf[0], 0, sizeof(buf)); logger << "socket closed for writing" << flush; return; } if(io!=NULL)BIO_free_all(io); } close(fd); memset(&buf[0], 0, sizeof(buf)); ss.clear(); //Logger::info("got new connection to process\n"+req->getFile()+" :: " + res.getStatusCode() + "\n"+req->getCntxt_name() + "\n"+req->getCntxt_root() + "\n"+req->getUrl()); delete req; logger << alldatlg << "--sent data--DONE" << flush; //sessionMap[sessId] = sess; } catch(...) { logger << "Standard exception: " << endl; } }
int MAIN(int argc, char **argv) { int off=0, clr = 0; SSL *con=NULL,*con2=NULL; X509_STORE *store = NULL; int s,k,width,state=0; char *cbuf=NULL,*sbuf=NULL,*mbuf=NULL; int cbuf_len,cbuf_off; int sbuf_len,sbuf_off; fd_set readfds,writefds; short port=PORT; int full_log=1; char *host=SSL_HOST_NAME; char *cert_file=NULL,*key_file=NULL; int cert_format = FORMAT_PEM, key_format = FORMAT_PEM; char *passarg = NULL, *pass = NULL; X509 *cert = NULL; EVP_PKEY *key = NULL; char *CApath=NULL,*CAfile=NULL,*cipher=NULL; int reconnect=0,badop=0,verify=SSL_VERIFY_NONE,bugs=0; int cutthrough=0; int crlf=0; int write_tty,read_tty,write_ssl,read_ssl,tty_on,ssl_pending; SSL_CTX *ctx=NULL; int ret=1,in_init=1,i,nbio_test=0; int starttls_proto = PROTO_OFF; int prexit = 0, vflags = 0; SSL_METHOD *meth=NULL; #ifdef sock_type #undef sock_type #endif int sock_type=SOCK_STREAM; BIO *sbio; char *inrand=NULL; int mbuf_len=0; struct timeval timeout, *timeoutp; #ifndef OPENSSL_NO_ENGINE char *engine_id=NULL; char *ssl_client_engine_id=NULL; ENGINE *ssl_client_engine=NULL; #endif ENGINE *e=NULL; #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) struct timeval tv; #endif #ifndef OPENSSL_NO_TLSEXT char *servername = NULL; tlsextctx tlsextcbp = {NULL,0}; #endif char *sess_in = NULL; char *sess_out = NULL; struct sockaddr peer; int peerlen = sizeof(peer); int enable_timeouts = 0 ; long socket_mtu = 0; #ifndef OPENSSL_NO_JPAKE char *jpake_secret = NULL; #endif #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) meth=SSLv23_client_method(); #elif !defined(OPENSSL_NO_SSL3) meth=SSLv3_client_method(); #elif !defined(OPENSSL_NO_SSL2) meth=SSLv2_client_method(); #endif apps_startup(); c_Pause=0; c_quiet=0; c_ign_eof=0; c_debug=0; c_msg=0; c_showcerts=0; if (bio_err == NULL) bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); if (!load_config(bio_err, NULL)) goto end; if ( ((cbuf=OPENSSL_malloc(BUFSIZZ)) == NULL) || ((sbuf=OPENSSL_malloc(BUFSIZZ)) == NULL) || ((mbuf=OPENSSL_malloc(BUFSIZZ)) == NULL)) { BIO_printf(bio_err,"out of memory\n"); goto end; } verify_depth=0; verify_error=X509_V_OK; #ifdef FIONBIO c_nbio=0; #endif argc--; argv++; while (argc >= 1) { if (strcmp(*argv,"-host") == 0) { if (--argc < 1) goto bad; host= *(++argv); } else if (strcmp(*argv,"-port") == 0) { if (--argc < 1) goto bad; port=atoi(*(++argv)); if (port == 0) goto bad; } else if (strcmp(*argv,"-connect") == 0) { if (--argc < 1) goto bad; if (!extract_host_port(*(++argv),&host,NULL,&port)) goto bad; } else if (strcmp(*argv,"-verify") == 0) { verify=SSL_VERIFY_PEER; if (--argc < 1) goto bad; verify_depth=atoi(*(++argv)); BIO_printf(bio_err,"verify depth is %d\n",verify_depth); } else if (strcmp(*argv,"-cert") == 0) { if (--argc < 1) goto bad; cert_file= *(++argv); } else if (strcmp(*argv,"-sess_out") == 0) { if (--argc < 1) goto bad; sess_out = *(++argv); } else if (strcmp(*argv,"-sess_in") == 0) { if (--argc < 1) goto bad; sess_in = *(++argv); } else if (strcmp(*argv,"-certform") == 0) { if (--argc < 1) goto bad; cert_format = str2fmt(*(++argv)); } else if (strcmp(*argv,"-crl_check") == 0) vflags |= X509_V_FLAG_CRL_CHECK; else if (strcmp(*argv,"-crl_check_all") == 0) vflags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL; else if (strcmp(*argv,"-prexit") == 0) prexit=1; else if (strcmp(*argv,"-crlf") == 0) crlf=1; else if (strcmp(*argv,"-quiet") == 0) { c_quiet=1; c_ign_eof=1; } else if (strcmp(*argv,"-ign_eof") == 0) c_ign_eof=1; else if (strcmp(*argv,"-no_ign_eof") == 0) c_ign_eof=0; else if (strcmp(*argv,"-pause") == 0) c_Pause=1; else if (strcmp(*argv,"-debug") == 0) c_debug=1; #ifndef OPENSSL_NO_TLSEXT else if (strcmp(*argv,"-tlsextdebug") == 0) c_tlsextdebug=1; else if (strcmp(*argv,"-status") == 0) c_status_req=1; #endif #ifdef WATT32 else if (strcmp(*argv,"-wdebug") == 0) dbug_init(); #endif else if (strcmp(*argv,"-msg") == 0) c_msg=1; else if (strcmp(*argv,"-showcerts") == 0) c_showcerts=1; else if (strcmp(*argv,"-nbio_test") == 0) nbio_test=1; else if (strcmp(*argv,"-state") == 0) state=1; #ifndef OPENSSL_NO_SSL2 else if (strcmp(*argv,"-ssl2") == 0) meth=SSLv2_client_method(); #endif #ifndef OPENSSL_NO_SSL3 else if (strcmp(*argv,"-ssl3") == 0) meth=SSLv3_client_method(); #endif #ifndef OPENSSL_NO_TLS1 else if (strcmp(*argv,"-tls1") == 0) meth=TLSv1_client_method(); #endif #ifndef OPENSSL_NO_DTLS1 else if (strcmp(*argv,"-dtls1") == 0) { meth=DTLSv1_client_method(); sock_type=SOCK_DGRAM; } else if (strcmp(*argv,"-timeout") == 0) enable_timeouts=1; else if (strcmp(*argv,"-mtu") == 0) { if (--argc < 1) goto bad; socket_mtu = atol(*(++argv)); } #endif else if (strcmp(*argv,"-bugs") == 0) bugs=1; else if (strcmp(*argv,"-keyform") == 0) { if (--argc < 1) goto bad; key_format = str2fmt(*(++argv)); } else if (strcmp(*argv,"-pass") == 0) { if (--argc < 1) goto bad; passarg = *(++argv); } else if (strcmp(*argv,"-key") == 0) { if (--argc < 1) goto bad; key_file= *(++argv); } else if (strcmp(*argv,"-reconnect") == 0) { reconnect=5; } else if (strcmp(*argv,"-CApath") == 0) { if (--argc < 1) goto bad; CApath= *(++argv); } else if (strcmp(*argv,"-CAfile") == 0) { if (--argc < 1) goto bad; CAfile= *(++argv); } else if (strcmp(*argv,"-no_tls1") == 0) off|=SSL_OP_NO_TLSv1; else if (strcmp(*argv,"-no_ssl3") == 0) off|=SSL_OP_NO_SSLv3; else if (strcmp(*argv,"-no_ssl2") == 0) off|=SSL_OP_NO_SSLv2; #ifndef OPENSSL_NO_TLSEXT else if (strcmp(*argv,"-no_ticket") == 0) { off|=SSL_OP_NO_TICKET; } #endif else if (strcmp(*argv,"-cutthrough") == 0) cutthrough=1; else if (strcmp(*argv,"-serverpref") == 0) off|=SSL_OP_CIPHER_SERVER_PREFERENCE; else if (strcmp(*argv,"-legacy_renegotiation") == 0) off|=SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; else if (strcmp(*argv,"-legacy_server_connect") == 0) { off|=SSL_OP_LEGACY_SERVER_CONNECT; } else if (strcmp(*argv,"-no_legacy_server_connect") == 0) { clr|=SSL_OP_LEGACY_SERVER_CONNECT; } else if (strcmp(*argv,"-cipher") == 0) { if (--argc < 1) goto bad; cipher= *(++argv); } #ifdef FIONBIO else if (strcmp(*argv,"-nbio") == 0) { c_nbio=1; } #endif else if (strcmp(*argv,"-starttls") == 0) { if (--argc < 1) goto bad; ++argv; if (strcmp(*argv,"smtp") == 0) starttls_proto = PROTO_SMTP; else if (strcmp(*argv,"pop3") == 0) starttls_proto = PROTO_POP3; else if (strcmp(*argv,"imap") == 0) starttls_proto = PROTO_IMAP; else if (strcmp(*argv,"ftp") == 0) starttls_proto = PROTO_FTP; else if (strcmp(*argv, "xmpp") == 0) starttls_proto = PROTO_XMPP; else goto bad; } #ifndef OPENSSL_NO_ENGINE else if (strcmp(*argv,"-engine") == 0) { if (--argc < 1) goto bad; engine_id = *(++argv); } else if (strcmp(*argv,"-ssl_client_engine") == 0) { if (--argc < 1) goto bad; ssl_client_engine_id = *(++argv); } #endif else if (strcmp(*argv,"-rand") == 0) { if (--argc < 1) goto bad; inrand= *(++argv); } #ifndef OPENSSL_NO_TLSEXT else if (strcmp(*argv,"-servername") == 0) { if (--argc < 1) goto bad; servername= *(++argv); /* meth=TLSv1_client_method(); */ } #endif #ifndef OPENSSL_NO_JPAKE else if (strcmp(*argv,"-jpake") == 0) { if (--argc < 1) goto bad; jpake_secret = *++argv; } #endif else { BIO_printf(bio_err,"unknown option %s\n",*argv); badop=1; break; } argc--; argv++; } if (badop) { bad: sc_usage(); goto end; } OpenSSL_add_ssl_algorithms(); SSL_load_error_strings(); #ifndef OPENSSL_NO_ENGINE e = setup_engine(bio_err, engine_id, 1); if (ssl_client_engine_id) { ssl_client_engine = ENGINE_by_id(ssl_client_engine_id); if (!ssl_client_engine) { BIO_printf(bio_err, "Error getting client auth engine\n"); goto end; } } #endif if (!app_passwd(bio_err, passarg, NULL, &pass, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } if (key_file == NULL) key_file = cert_file; if (key_file) { key = load_key(bio_err, key_file, key_format, 0, pass, e, "client certificate private key file"); if (!key) { ERR_print_errors(bio_err); goto end; } } if (cert_file) { cert = load_cert(bio_err,cert_file,cert_format, NULL, e, "client certificate file"); if (!cert) { ERR_print_errors(bio_err); goto end; } } if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL && !RAND_status()) { BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n"); } if (inrand != NULL) BIO_printf(bio_err,"%ld semi-random bytes loaded\n", app_RAND_load_files(inrand)); if (bio_c_out == NULL) { if (c_quiet && !c_debug && !c_msg) { bio_c_out=BIO_new(BIO_s_null()); } else { if (bio_c_out == NULL) bio_c_out=BIO_new_fp(stdout,BIO_NOCLOSE); } } ctx=SSL_CTX_new(meth); if (ctx == NULL) { ERR_print_errors(bio_err); goto end; } #ifndef OPENSSL_NO_ENGINE if (ssl_client_engine) { if (!SSL_CTX_set_client_cert_engine(ctx, ssl_client_engine)) { BIO_puts(bio_err, "Error setting client auth engine\n"); ERR_print_errors(bio_err); ENGINE_free(ssl_client_engine); goto end; } ENGINE_free(ssl_client_engine); } #endif if (bugs) SSL_CTX_set_options(ctx,SSL_OP_ALL|off); else SSL_CTX_set_options(ctx,off); if (clr) SSL_CTX_clear_options(ctx, clr); /* DTLS: partial reads end up discarding unread UDP bytes :-( * Setting read ahead solves this problem. */ if (sock_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1); /* Enable handshake cutthrough for client connections using * strong ciphers. */ if (cutthrough) { int ssl_mode = SSL_CTX_get_mode(ctx); ssl_mode |= SSL_MODE_HANDSHAKE_CUTTHROUGH; SSL_CTX_set_mode(ctx, ssl_mode); } if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback); if (cipher != NULL) if(!SSL_CTX_set_cipher_list(ctx,cipher)) { BIO_printf(bio_err,"error setting cipher list\n"); ERR_print_errors(bio_err); goto end; } #if 0 else SSL_CTX_set_cipher_list(ctx,getenv("SSL_CIPHER")); #endif SSL_CTX_set_verify(ctx,verify,verify_callback); if (!set_cert_key_stuff(ctx,cert,key)) goto end; if ((!SSL_CTX_load_verify_locations(ctx,CAfile,CApath)) || (!SSL_CTX_set_default_verify_paths(ctx))) { /* BIO_printf(bio_err,"error setting default verify locations\n"); */ ERR_print_errors(bio_err); /* goto end; */ } store = SSL_CTX_get_cert_store(ctx); X509_STORE_set_flags(store, vflags); #ifndef OPENSSL_NO_TLSEXT if (servername != NULL) { tlsextcbp.biodebug = bio_err; SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp); } #endif con=SSL_new(ctx); if (sess_in) { SSL_SESSION *sess; BIO *stmp = BIO_new_file(sess_in, "r"); if (!stmp) { BIO_printf(bio_err, "Can't open session file %s\n", sess_in); ERR_print_errors(bio_err); goto end; } sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL); BIO_free(stmp); if (!sess) { BIO_printf(bio_err, "Can't open session file %s\n", sess_in); ERR_print_errors(bio_err); goto end; } SSL_set_session(con, sess); SSL_SESSION_free(sess); } #ifndef OPENSSL_NO_TLSEXT if (servername != NULL) { if (!SSL_set_tlsext_host_name(con,servername)) { BIO_printf(bio_err,"Unable to set TLS servername extension.\n"); ERR_print_errors(bio_err); goto end; } } #endif #ifndef OPENSSL_NO_KRB5 if (con && (con->kssl_ctx = kssl_ctx_new()) != NULL) { kssl_ctx_setstring(con->kssl_ctx, KSSL_SERVER, host); } #endif /* OPENSSL_NO_KRB5 */ /* SSL_set_cipher_list(con,"RC4-MD5"); */ re_start: if (init_client(&s,host,port,sock_type) == 0) { BIO_printf(bio_err,"connect:errno=%d\n",get_last_socket_error()); SHUTDOWN(s); goto end; } BIO_printf(bio_c_out,"CONNECTED(%08X)\n",s); #ifdef FIONBIO if (c_nbio) { unsigned long l=1; BIO_printf(bio_c_out,"turning on non blocking io\n"); if (BIO_socket_ioctl(s,FIONBIO,&l) < 0) { ERR_print_errors(bio_err); goto end; } } #endif if (c_Pause & 0x01) con->debug=1; if ( SSL_version(con) == DTLS1_VERSION) { sbio=BIO_new_dgram(s,BIO_NOCLOSE); if (getsockname(s, &peer, (void *)&peerlen) < 0) { BIO_printf(bio_err, "getsockname:errno=%d\n", get_last_socket_error()); SHUTDOWN(s); goto end; } (void)BIO_ctrl_set_connected(sbio, 1, &peer); if ( enable_timeouts) { timeout.tv_sec = 0; timeout.tv_usec = DGRAM_RCV_TIMEOUT; BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); timeout.tv_sec = 0; timeout.tv_usec = DGRAM_SND_TIMEOUT; BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout); } if (socket_mtu > 28) { SSL_set_options(con, SSL_OP_NO_QUERY_MTU); SSL_set_mtu(con, socket_mtu - 28); } else /* want to do MTU discovery */ BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); } else sbio=BIO_new_socket(s,BIO_NOCLOSE); if (nbio_test) { BIO *test; test=BIO_new(BIO_f_nbio_test()); sbio=BIO_push(test,sbio); } if (c_debug) { con->debug=1; BIO_set_callback(sbio,bio_dump_callback); BIO_set_callback_arg(sbio,(char *)bio_c_out); } if (c_msg) { SSL_set_msg_callback(con, msg_cb); SSL_set_msg_callback_arg(con, bio_c_out); } #ifndef OPENSSL_NO_TLSEXT if (c_tlsextdebug) { SSL_set_tlsext_debug_callback(con, tlsext_cb); SSL_set_tlsext_debug_arg(con, bio_c_out); } if (c_status_req) { SSL_set_tlsext_status_type(con, TLSEXT_STATUSTYPE_ocsp); SSL_CTX_set_tlsext_status_cb(ctx, ocsp_resp_cb); SSL_CTX_set_tlsext_status_arg(ctx, bio_c_out); #if 0 { STACK_OF(OCSP_RESPID) *ids = sk_OCSP_RESPID_new_null(); OCSP_RESPID *id = OCSP_RESPID_new(); id->value.byKey = ASN1_OCTET_STRING_new(); id->type = V_OCSP_RESPID_KEY; ASN1_STRING_set(id->value.byKey, "Hello World", -1); sk_OCSP_RESPID_push(ids, id); SSL_set_tlsext_status_ids(con, ids); } #endif } #endif #ifndef OPENSSL_NO_JPAKE if (jpake_secret) jpake_client_auth(bio_c_out, sbio, jpake_secret); #endif SSL_set_bio(con,sbio,sbio); SSL_set_connect_state(con); /* ok, lets connect */ width=SSL_get_fd(con)+1; read_tty=1; write_tty=0; tty_on=0; read_ssl=1; write_ssl=1; cbuf_len=0; cbuf_off=0; sbuf_len=0; sbuf_off=0; /* This is an ugly hack that does a lot of assumptions */ /* We do have to handle multi-line responses which may come in a single packet or not. We therefore have to use BIO_gets() which does need a buffering BIO. So during the initial chitchat we do push a buffering BIO into the chain that is removed again later on to not disturb the rest of the s_client operation. */ if (starttls_proto == PROTO_SMTP) { int foundit=0; BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); /* wait for multi-line response to end from SMTP */ do { mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); } while (mbuf_len>3 && mbuf[3]=='-'); /* STARTTLS command requires EHLO... */ BIO_printf(fbio,"EHLO openssl.client.net\r\n"); (void)BIO_flush(fbio); /* wait for multi-line response to end EHLO SMTP response */ do { mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); if (strstr(mbuf,"STARTTLS")) foundit=1; } while (mbuf_len>3 && mbuf[3]=='-'); (void)BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); if (!foundit) BIO_printf(bio_err, "didn't found starttls in server response," " try anyway...\n"); BIO_printf(sbio,"STARTTLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } else if (starttls_proto == PROTO_POP3) { BIO_read(sbio,mbuf,BUFSIZZ); BIO_printf(sbio,"STLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } else if (starttls_proto == PROTO_IMAP) { int foundit=0; BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); BIO_gets(fbio,mbuf,BUFSIZZ); /* STARTTLS command requires CAPABILITY... */ BIO_printf(fbio,". CAPABILITY\r\n"); (void)BIO_flush(fbio); /* wait for multi-line CAPABILITY response */ do { mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); if (strstr(mbuf,"STARTTLS")) foundit=1; } while (mbuf_len>3 && mbuf[0]!='.'); (void)BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); if (!foundit) BIO_printf(bio_err, "didn't found STARTTLS in server response," " try anyway...\n"); BIO_printf(sbio,". STARTTLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } else if (starttls_proto == PROTO_FTP) { BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); /* wait for multi-line response to end from FTP */ do { mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); } while (mbuf_len>3 && mbuf[3]=='-'); (void)BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); BIO_printf(sbio,"AUTH TLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } if (starttls_proto == PROTO_XMPP) { int seen = 0; BIO_printf(sbio,"<stream:stream " "xmlns:stream='http://etherx.jabber.org/streams' " "xmlns='jabber:client' to='%s' version='1.0'>", host); seen = BIO_read(sbio,mbuf,BUFSIZZ); mbuf[seen] = 0; while (!strstr(mbuf, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'")) { if (strstr(mbuf, "/stream:features>")) goto shut; seen = BIO_read(sbio,mbuf,BUFSIZZ); mbuf[seen] = 0; } BIO_printf(sbio, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); seen = BIO_read(sbio,sbuf,BUFSIZZ); sbuf[seen] = 0; if (!strstr(sbuf, "<proceed")) goto shut; mbuf[0] = 0; } for (;;) { FD_ZERO(&readfds); FD_ZERO(&writefds); if ((SSL_version(con) == DTLS1_VERSION) && DTLSv1_get_timeout(con, &timeout)) timeoutp = &timeout; else timeoutp = NULL; if (SSL_in_init(con) && !SSL_total_renegotiations(con)) { in_init=1; tty_on=0; } else { tty_on=1; if (in_init) { in_init=0; if (sess_out) { BIO *stmp = BIO_new_file(sess_out, "w"); if (stmp) { PEM_write_bio_SSL_SESSION(stmp, SSL_get_session(con)); BIO_free(stmp); } else BIO_printf(bio_err, "Error writing session file %s\n", sess_out); } print_stuff(bio_c_out,con,full_log); if (full_log > 0) full_log--; if (starttls_proto) { BIO_printf(bio_err,"%s",mbuf); /* We don't need to know any more */ starttls_proto = PROTO_OFF; } if (reconnect) { reconnect--; BIO_printf(bio_c_out,"drop connection and then reconnect\n"); SSL_shutdown(con); SSL_set_connect_state(con); SHUTDOWN(SSL_get_fd(con)); goto re_start; } } } ssl_pending = read_ssl && SSL_pending(con); if (!ssl_pending) { #if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_NETWARE) if (tty_on) { if (read_tty) FD_SET(fileno(stdin),&readfds); if (write_tty) FD_SET(fileno(stdout),&writefds); } if (read_ssl) FD_SET(SSL_get_fd(con),&readfds); if (write_ssl) FD_SET(SSL_get_fd(con),&writefds); #else if(!tty_on || !write_tty) { if (read_ssl) FD_SET(SSL_get_fd(con),&readfds); if (write_ssl) FD_SET(SSL_get_fd(con),&writefds); } #endif /* printf("mode tty(%d %d%d) ssl(%d%d)\n", tty_on,read_tty,write_tty,read_ssl,write_ssl);*/ /* Note: under VMS with SOCKETSHR the second parameter * is currently of type (int *) whereas under other * systems it is (void *) if you don't have a cast it * will choke the compiler: if you do have a cast then * you can either go for (int *) or (void *). */ #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) /* Under Windows/DOS we make the assumption that we can * always write to the tty: therefore if we need to * write to the tty we just fall through. Otherwise * we timeout the select every second and see if there * are any keypresses. Note: this is a hack, in a proper * Windows application we wouldn't do this. */ i=0; if(!write_tty) { if(read_tty) { tv.tv_sec = 1; tv.tv_usec = 0; i=select(width,(void *)&readfds,(void *)&writefds, NULL,&tv); #if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS) if(!i && (!_kbhit() || !read_tty) ) continue; #else if(!i && (!((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) || !read_tty) ) continue; #endif } else i=select(width,(void *)&readfds,(void *)&writefds, NULL,timeoutp); } #elif defined(OPENSSL_SYS_NETWARE) if(!write_tty) { if(read_tty) { tv.tv_sec = 1; tv.tv_usec = 0; i=select(width,(void *)&readfds,(void *)&writefds, NULL,&tv); } else i=select(width,(void *)&readfds,(void *)&writefds, NULL,timeoutp); } #else i=select(width,(void *)&readfds,(void *)&writefds, NULL,timeoutp); #endif if ( i < 0) { BIO_printf(bio_err,"bad select %d\n", get_last_socket_error()); goto shut; /* goto end; */ } } if ((SSL_version(con) == DTLS1_VERSION) && DTLSv1_handle_timeout(con) > 0) { BIO_printf(bio_err,"TIMEOUT occured\n"); } if (!ssl_pending && FD_ISSET(SSL_get_fd(con),&writefds)) { k=SSL_write(con,&(cbuf[cbuf_off]), (unsigned int)cbuf_len); switch (SSL_get_error(con,k)) { case SSL_ERROR_NONE: cbuf_off+=k; cbuf_len-=k; if (k <= 0) goto end; /* we have done a write(con,NULL,0); */ if (cbuf_len <= 0) { read_tty=1; write_ssl=0; } else /* if (cbuf_len > 0) */ { read_tty=0; write_ssl=1; } break; case SSL_ERROR_WANT_WRITE: BIO_printf(bio_c_out,"write W BLOCK\n"); write_ssl=1; read_tty=0; break; case SSL_ERROR_WANT_READ: BIO_printf(bio_c_out,"write R BLOCK\n"); write_tty=0; read_ssl=1; write_ssl=0; break; case SSL_ERROR_WANT_X509_LOOKUP: BIO_printf(bio_c_out,"write X BLOCK\n"); break; case SSL_ERROR_ZERO_RETURN: if (cbuf_len != 0) { BIO_printf(bio_c_out,"shutdown\n"); goto shut; } else { read_tty=1; write_ssl=0; break; } case SSL_ERROR_SYSCALL: if ((k != 0) || (cbuf_len != 0)) { BIO_printf(bio_err,"write:errno=%d\n", get_last_socket_error()); goto shut; } else { read_tty=1; write_ssl=0; } break; case SSL_ERROR_SSL: ERR_print_errors(bio_err); goto shut; } } #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) /* Assume Windows/DOS can always write */ else if (!ssl_pending && write_tty) #else else if (!ssl_pending && FD_ISSET(fileno(stdout),&writefds)) #endif { #ifdef CHARSET_EBCDIC ascii2ebcdic(&(sbuf[sbuf_off]),&(sbuf[sbuf_off]),sbuf_len); #endif i=write(fileno(stdout),&(sbuf[sbuf_off]),sbuf_len); if (i <= 0) { BIO_printf(bio_c_out,"DONE\n"); goto shut; /* goto end; */ } sbuf_len-=i;; sbuf_off+=i; if (sbuf_len <= 0) { read_ssl=1; write_tty=0; } } else if (ssl_pending || FD_ISSET(SSL_get_fd(con),&readfds)) { #ifdef RENEG { static int iiii; if (++iiii == 52) { SSL_renegotiate(con); iiii=0; } } #endif #if 1 k=SSL_read(con,sbuf,1024 /* BUFSIZZ */ ); #else /* Demo for pending and peek :-) */ k=SSL_read(con,sbuf,16); { char zbuf[10240]; printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240)); } #endif switch (SSL_get_error(con,k)) { case SSL_ERROR_NONE: if (k <= 0) goto end; sbuf_off=0; sbuf_len=k; read_ssl=0; write_tty=1; break; case SSL_ERROR_WANT_WRITE: BIO_printf(bio_c_out,"read W BLOCK\n"); write_ssl=1; read_tty=0; break; case SSL_ERROR_WANT_READ: BIO_printf(bio_c_out,"read R BLOCK\n"); write_tty=0; read_ssl=1; if ((read_tty == 0) && (write_ssl == 0)) write_ssl=1; break; case SSL_ERROR_WANT_X509_LOOKUP: BIO_printf(bio_c_out,"read X BLOCK\n"); break; case SSL_ERROR_SYSCALL: BIO_printf(bio_err,"read:errno=%d\n",get_last_socket_error()); goto shut; case SSL_ERROR_ZERO_RETURN: BIO_printf(bio_c_out,"closed\n"); goto shut; case SSL_ERROR_SSL: ERR_print_errors(bio_err); goto shut; /* break; */ } } #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) #if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS) else if (_kbhit()) #else else if ((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) #endif #elif defined (OPENSSL_SYS_NETWARE) else if (_kbhit()) #else else if (FD_ISSET(fileno(stdin),&readfds)) #endif { if (crlf) { int j, lf_num; i=read(fileno(stdin),cbuf,BUFSIZZ/2); lf_num = 0; /* both loops are skipped when i <= 0 */ for (j = 0; j < i; j++) if (cbuf[j] == '\n') lf_num++; for (j = i-1; j >= 0; j--) { cbuf[j+lf_num] = cbuf[j]; if (cbuf[j] == '\n') { lf_num--; i++; cbuf[j+lf_num] = '\r'; } } assert(lf_num == 0); } else i=read(fileno(stdin),cbuf,BUFSIZZ); if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q'))) { BIO_printf(bio_err,"DONE\n"); goto shut; } if ((!c_ign_eof) && (cbuf[0] == 'R')) { BIO_printf(bio_err,"RENEGOTIATING\n"); SSL_renegotiate(con); cbuf_len=0; } else { cbuf_len=i; cbuf_off=0; #ifdef CHARSET_EBCDIC ebcdic2ascii(cbuf, cbuf, i); #endif } write_ssl=1; read_tty=0; } } shut: SSL_shutdown(con); SHUTDOWN(SSL_get_fd(con)); ret=0; end: if(prexit) print_stuff(bio_c_out,con,1); if (con != NULL) SSL_free(con); if (con2 != NULL) SSL_free(con2); if (ctx != NULL) SSL_CTX_free(ctx); if (cert) X509_free(cert); if (key) EVP_PKEY_free(key); if (pass) OPENSSL_free(pass); if (cbuf != NULL) { OPENSSL_cleanse(cbuf,BUFSIZZ); OPENSSL_free(cbuf); } if (sbuf != NULL) { OPENSSL_cleanse(sbuf,BUFSIZZ); OPENSSL_free(sbuf); } if (mbuf != NULL) { OPENSSL_cleanse(mbuf,BUFSIZZ); OPENSSL_free(mbuf); } if (bio_c_out != NULL) { BIO_free(bio_c_out); bio_c_out=NULL; } apps_shutdown(); OPENSSL_EXIT(ret); }