int PKI_HTTP_get_socket (const PKI_SOCKET * sock, const char * data, size_t data_size, const char * content_type, int method, int timeout, size_t max_size, PKI_MEM_STACK ** sk ) { size_t len = 0; const char *my_cont_type = "application/unknown"; PKI_HTTP *http_rv = NULL; int rv = -1; int ret = PKI_OK; size_t max_len = 0; size_t auth_len = 0; char *tmp = NULL; char *auth_tmp = NULL; char *head_get = "GET %s HTTP/1.1\r\n" "Host: %s\r\n" "User-Agent: LibPKI\r\n" "Connection: close\r\n" "%s"; char *head_post = "POST %s HTTP/1.1\r\n" "Host: %s\r\n" "User-Agent: LibPKI\r\n" "Connection: close\r\n" "Content-type: %s\r\n" "Content-Length: %d\r\n" "%s"; char *head = NULL; if ( timeout < 0 ) timeout = 0; if ( !sock || !sock->url ) return PKI_ERR; // Process the authentication information if provided by the caller if (sock->url && sock->url->usr && sock->url->pwd) { // Rough estimate for the auth string max_len = strlen(sock->url->usr) + strlen(sock->url->pwd) + 100; // Special case for when a usr/pwd was specified in the URL auth_tmp = PKI_Malloc(len); auth_len = (size_t)snprintf(auth_tmp, len, "Authentication: user %s:%s\r\n\r\n", sock->url->usr, sock->url->pwd); } else { // If we do not have the auth info, we just add the end of header auth_len = 2; auth_tmp = "\r\n"; } if (method == PKI_HTTP_METHOD_GET) { // Gets the right header head = head_get; // Estimate the header's final size max_len = strlen(head) + strlen(sock->url->path) + strlen(sock->url->addr) + 101; // Allocates enough space for the header tmp = PKI_Malloc ( max_len + auth_len ); // Prints the header into the tmp container len = (size_t) snprintf(tmp, max_len, head, sock->url->path, sock->url->addr, auth_tmp); } else if (method == PKI_HTTP_METHOD_POST) { // Gets the right head head = head_post; // Determines the right content type if ( content_type ) my_cont_type = content_type; else my_cont_type = "text/html"; // Checks the max len for the allocated header max_len = strlen(head) + strlen(sock->url->path) + strlen(sock->url->addr) + strlen(my_cont_type) + 101; // Allocates the memory for the header tmp = PKI_Malloc ( max_len + auth_len ); // Prints the header into the tmp container len = (size_t) snprintf(tmp, max_len, head, sock->url->path, sock->url->addr, my_cont_type, data_size, auth_tmp ); } else { PKI_log_err ( "Method (%d) not supported!", method ); return PKI_ERR; } // PKI_MEM *r = PKI_MEM_new_data(len, tmp); // URL_put_data("file://http_req.txt", r, NULL, NULL, 0, 0, NULL); // PKI_MEM_free(r); if ((rv = (int) PKI_SOCKET_write(sock, tmp, len)) < 0) { PKI_log_err("Can not write HTTP header to socket"); PKI_Free(tmp); goto err; } // Free the tmp pointer that held the request header if (tmp) PKI_Free (tmp); // If we were using a POST method, we need to actually send the data if(data != NULL) { PKI_log_err("{DEBUG} Writing Data -> data_size = %d, data = %p", data_size, data); if ((PKI_SOCKET_write(sock, data, data_size)) < 0) { PKI_log_err ("Can not write POST to socket."); goto err; } } // Let's now wait for the response from the server if ((http_rv = PKI_HTTP_get_message(sock, timeout, max_size)) == NULL) { PKI_log_err ("HTTP retrieval error\n"); goto err; } // We shall now check for the return code if (http_rv->code >= 400 ) { goto err; } else if (http_rv->code >= 300) { /* Redirection - let's try that */ if (http_rv->location == NULL) { PKI_log_debug ( "HTTP Redirection but no location provided!"); goto err; } PKI_log_debug("HTTP Redirection Detected [URL: %s]", http_rv->location ); if (strstr(http_rv->location, "://") != NULL) { URL *url_tmp = NULL; if( strncmp_nocase( http_rv->location, sock->url->url_s, (int) strlen(http_rv->location)) == 0) { PKI_log_debug( "HTTP cyclic redirection!"); goto err; } if ((url_tmp = URL_new ( http_rv->location )) == NULL) { PKI_log_debug("HTTP location is not a valid URI (%s)", http_rv->location ); goto err; } if ( sock->url->ssl == 0 ) { ret = PKI_HTTP_get_url ( url_tmp, data, data_size, content_type, method, timeout, max_size, sk, NULL ); } else { PKI_SSL *ssl2 = PKI_SSL_dup ( sock->ssl ); ret = PKI_HTTP_get_url ( url_tmp, data, data_size, content_type, method, timeout, max_size, sk, ssl2 ); } if ( url_tmp ) URL_free ( url_tmp ); goto end; } else { const char *prot_s = NULL; char new_url[2048]; URL *my_new_url = NULL; PKI_SSL *ssl2 = PKI_SSL_dup ( sock->ssl ); prot_s = URL_proto_to_string ( sock->url->proto ); if( !prot_s ) goto err; snprintf(new_url, sizeof(new_url),"%s://%s%s", prot_s, sock->url->addr, http_rv->location ); if( strncmp_nocase( new_url, sock->url->url_s, (int) strlen ( new_url )) == 0 ) { PKI_log_debug( "HTTP cyclic redirection!"); goto err; } my_new_url = URL_new ( new_url ); ret = PKI_HTTP_get_url ( my_new_url, data, data_size, content_type, method, timeout, max_size, sk, ssl2 ); if (ssl2) PKI_SSL_free ( ssl2 ); } } else if (http_rv->code != 200) { PKI_log_debug( "Unknown HTTP Return code [Code: %d]", http_rv->code ); goto err; } /* PKI_log_err("{DEBUG} method = %d, header->size = %d, body = %p, body_size = %d", http_rv->method, http_rv->head->size, http_rv->body, http_rv->body->size); URL_put_data("file://http-resp-header.txt", http_rv->head, NULL, NULL, 0, 0, NULL); URL_put_data("file://http-resp-data.txt", http_rv->body, NULL, NULL, 0, 0, NULL); */ // If a Pointer was provided, we want the data back if (sk) { // Checks if the caller provided an already allocated data // structure. If not, we allocate it. if (*sk) PKI_STACK_MEM_free_all(*sk); // Allocates a new structure if ((*sk = PKI_STACK_MEM_new()) == NULL) { // If a memory error occurs report it and exit PKI_ERROR(PKI_ERR_MEMORY_ALLOC, NULL); // Nothing more to do goto err; } // Add the returned value to the stack if (PKI_STACK_MEM_push(*sk, http_rv->body) != PKI_OK) { PKI_log_err("Can not push the HTTP result body in the result stack"); goto err; } // Remove ownership of the body PKI_MEM from the original // HTTP msg container http_rv->body = NULL; } end: // Finally free the HTTP message memory if (http_rv) PKI_HTTP_free(http_rv); // Returns the result return ret; err: // Error condition if (http_rv) PKI_HTTP_free ( http_rv ); // Free the locally allocated memory if (*sk) PKI_STACK_MEM_free_all(*sk); *sk = NULL; return PKI_ERR; }
/*! \brief Returns a MEM STACK with the requested DNS records */ PKI_MEM_STACK *URL_get_data_dns_url(URL *url, ssize_t size) { PKI_MEM_STACK *ret = NULL; #ifdef HAVE_LIBRESOLV int type = T_A; PKI_MEM *obj = NULL; if( (!url) || (!url->addr)) { return NULL; } unsigned char response[NS_PACKETSZ]; ns_msg dnsMessage; ns_rr dnsRecord; int dnsRecordSection = ns_s_an; int dns_msgCount = 0; int len = 0; // Check the Type of record if ((type = URL_get_dns_type(url->attrs)) == -1) return NULL; PKI_log_debug("DNS URI: Searching for %s (%s/%d)", url->addr, url->attrs, type); if ((len = res_search(url->addr, C_IN, type, response, sizeof(response))) < 0) { // An Error Occurred PKI_log_err("DNS URI: search failed\n"); return NULL; } if (ns_initparse(response, len, &dnsMessage) < 0) { // This should not happen if the record is correct PKI_log_err("DNS URI: can not init DNS parsing of the dnsMessage\n"); return NULL; } len = ns_msg_count(dnsMessage, dnsRecordSection); PKI_log_debug("DNS_URI: msg count ==> %d\n", len); if (len <= 0) return NULL; if((ret = PKI_STACK_MEM_new()) == NULL ) { PKI_log_debug ("DNS URI: Memory Failure"); return NULL; } for (dns_msgCount = 0; dns_msgCount < len; dns_msgCount++) { PKI_log_debug("DNS URI: Retrieving DNS record #%d",dns_msgCount); if (ns_parserr(&dnsMessage, dnsRecordSection, dns_msgCount, &dnsRecord)) { // ERROR: ns_parserr failed, let's continue to the next record PKI_log_err("DNS URI: Can not parse record %d of %d", dns_msgCount, len); continue; } PKI_log_debug("DNS URI: type = %d (req: %d)\n", ns_rr_type(dnsRecord), type); if (type == pki_ns_t_address) { switch (ns_rr_type(dnsRecord)) { case T_A: case T_AAAA: case T_CNAME: break; default: continue; } } else if (type != ns_rr_type(dnsRecord)) { PKI_log_debug("DNS URI: recived type %d is different from requested (%d)", type, ns_rr_type(dnsRecord)); // continue; } // int i = 0; int rv = 0; // int len = 0; int offset = 0; char dnsRecordName[MAXDNAME]; memset(dnsRecordName, '\x0', MAXDNAME); // Parse the different types of DNS records if ((ns_rr_type(dnsRecord) == T_A) || (ns_rr_type(dnsRecord) == T_AAAA)) { // These require Translation using IPv4/IPv6 functions int family = AF_INET; if (ns_rr_type(dnsRecord) == T_A) family = AF_INET; else family = AF_INET6; if(inet_ntop(family, ns_rr_rdata(dnsRecord), dnsRecordName, sizeof(dnsRecordName)) == NULL) { // Can not convert continue; } } else if ((ns_rr_type(dnsRecord) == T_CNAME) || (ns_rr_type(dnsRecord) == T_MX) || (ns_rr_type(dnsRecord) == T_NS)) { if (ns_rr_type(dnsRecord) == T_MX) offset = NS_INT16SZ; rv = ns_name_uncompress(ns_msg_base(dnsMessage), ns_msg_end(dnsMessage), ns_rr_rdata(dnsRecord) + offset, dnsRecordName, MAXDNAME); // ERROR, can not uncompress the names if (rv < 0) continue; } else if (ns_rr_type(dnsRecord) == T_SRV) { // This requires special handling, the format is [SHORT][SHORT][SHORT][DATA] // unsigned short *pri = (unsigned short *) ns_rr_rdata(dnsRecord); // unsigned short *weight = (unsigned short *) &(ns_rr_rdata(dnsRecord)[2]); // unsigned short *port = (unsigned short *) &(ns_rr_rdata(dnsRecord)[4]); // Shall we return the additional data too ? // printf("PRI : %d\n", *pri); // printf("WEIGHT : %d\n", ntohs(*weight)); // printf("PORT : %d\n", ntohs(*port)); offset = 6; rv = ns_name_uncompress(ns_msg_base(dnsMessage), ns_msg_end(dnsMessage), ns_rr_rdata(dnsRecord) + offset, dnsRecordName, MAXDNAME); if (rv < 0) continue; } else if (ns_rr_type(dnsRecord) == T_TXT) { // Special handling required. Format is [BYTE][DATA] unsigned char *p = (unsigned char *)ns_rr_rdata(dnsRecord); snprintf(dnsRecordName, (size_t) *p+1, "%s", &ns_rr_rdata(dnsRecord)[1]); } else { PKI_log_debug("DNS URI: record type not supported [%d]", ns_rr_type(dnsRecord)); continue; } if((obj = PKI_MEM_new_null()) == NULL ) { // Memory Allocation Error, we abort break; } if (strlen(dnsRecordName) > 0) { // If it is a printable value, we add the parsed version of the // record if(PKI_MEM_add(obj, (char *) dnsRecordName, strlen(dnsRecordName)) == PKI_ERR) { /* ERROR in memory growth */; PKI_log_err("DNS URI: Memory Allocation Error"); break; } } else { // The value is not parsed/parsable, we return the raw data // the application should know what to do with the data! if(PKI_MEM_add(obj, (char *) ns_rr_rdata(dnsRecord), ns_rr_rdlen(dnsRecord)) == PKI_ERR) { /* ERROR in memory growth */; PKI_log_err("DNS URI: Memory Allocation Error"); break; } } /* printf("MSG Data [%d]:\n", ns_rr_rdlen(dnsRecord)); for (i=0; i < ns_rr_rdlen(dnsRecord); i++) { unsigned char *kk; kk = (unsigned char *) &ns_rr_rdata(dnsRecord)[i]; printf("%x:", *kk); }; printf("\n"); fprintf(stderr, "DEBUG: RV => %d (err: %d, %s)\n", rv, h_errno, hstrerror(h_errno)); fprintf(stderr, "DEBUG: name => %s (%s)\n", ns_rr_name(dnsRecord), url->addr); fprintf(stderr, "DEBUG: value => %s\n", dnsRecordName); fprintf(stderr, "DEBUG: type => %d\n", ns_rr_type(dnsRecord)); fprintf(stderr, "DEBUG: class => %d\n", ns_rr_class(dnsRecord)); */ PKI_STACK_MEM_push(ret, obj); // PKI_log_debug("DNS URI: Added object #%d to stack", PKI_STACK_MEM_elements(ret)); } #endif return ret; };
PKI_MEM_STACK *URL_get_data_pkcs11_url ( URL *url, ssize_t size ) { #ifdef HAVE_P11 // PKCS11_CTX *ctx = NULL; PKCS11_SLOT *slots = NULL; PKCS11_TOKEN *tk = NULL; char *libfile = NULL; int num = 0; int i = 0; char * search_label = NULL; char * search_id = NULL; char * search_slot = NULL; char * search_slotid = NULL; PKI_MEM *tmp_mem = NULL; PKI_MEM_STACK *sk = NULL; if( !url ) return (NULL); /* if((libfile = pkcs11_parse_url_libpath ( url )) == NULL ) { return( NULL ); } */ /* slot = pkcs11_parse_url_slot ( url ); id = pkcs11_parse_url_id ( url ); */ if( ctx == NULL ) { if((ctx = PKCS11_CTX_new ()) == NULL ) { return(NULL); } PKI_log_debug("Loading %s Library", url->addr ); if(( i = PKCS11_CTX_load(ctx, url->addr)) != 0 ) { PKI_log_err("Can not load library %s [err::%d]", url->addr, i); // ERR_print_errors_fp( stderr ); } } if( PKCS11_enumerate_slots( ctx, &slots, &num ) == -1 ) { PKI_log_err ("Can not enumerate slots"); goto err; }; if(( sk = PKI_STACK_MEM_new()) == NULL ) { goto err; } search_slot = pkcs11_parse_url_getval( url, "slot" ); search_slotid = pkcs11_parse_url_getval( url, "slotid" ); search_label = pkcs11_parse_url_getval( url, "label" ); search_id = pkcs11_parse_url_getval( url, "id" ); if( search_slot ) PKI_log_debug("DEBUG::PKCS11::SEARCH::SLOT => %s\n", search_slot); if( search_slotid ) PKI_log_debug("DEBUG::PKCS11::SEARCH::SLOTID => %s\n", search_slotid); if( search_label ) PKI_log_debug("DEBUG::PKCS11::SEARCH::LABEL => %s\n", search_label); if( search_id ) PKI_log_debug("DEBUG::PKCS11::SEARCH::ID => %s\n", search_id); for(i = 0; i < num; i++ ) { BIO *mem = NULL; BUF_MEM *mem_buf = NULL; PKCS11_CERT *certs = NULL; PKCS11_SLOT *p = NULL; PKCS11_CERT *x = NULL; PKCS11_KEY *keyList = NULL; PKCS11_KEY *key = NULL; EVP_PKEY *evp_pkey = NULL; int n = 0; int t = 0; int n_objs = 0; int p_ret = 0; p = &slots[i]; if((!p) || ((tk = p->token) == NULL) ) { continue; } if( (search_slot) && ( strncmp_nocase( search_slot, tk->label, strlen(search_slot) == 0) )) { continue; } if( (search_slotid) && ( atoi(search_slotid) != i )) { PKI_log_debug("PKCS11::SLOTID is %s (%d), curr is %d\n", search_slotid, atoi(search_slotid), i); continue; } if( strncmp_nocase( url->attrs, "cert", 4 ) == 0) { PKI_log_debug("PKCS11::CERT DATATYPE SELECTED!\n"); if((mem = BIO_new(BIO_s_mem())) == NULL ) { goto err; } /* Get the list of certificates in the slot */ p_ret = PKCS11_enumerate_certs( tk, &certs, &n_objs); for( n = 0; n < n_objs; n++ ) { /* Pointer to the current certificate */ x = &certs[n]; PKI_log_debug("PKCS11::CERT label=%s\n", x->label); PKI_log_debug("PKCS11::CERT id="); for( t = 0; t < x->id_len; t ++ ) { printf("%c", x->id[t] ); } printf("\n"); if( (search_label) && (strncmp_nocase( search_label, x->label, strlen( search_label)) != 0 )){ PKI_log_debug("PKCS11::LABEL does not" "match, SKIPPING!!!!\n"); continue; } if( search_id ) { int stop = 0; for( t = 0; t < x->id_len; t ++ ) { if( search_id[t] != x->id[t] ) { stop = 1; break; } } if( stop == 1 ) { printf("DEBUG::PKCS11::ID does not" "match, SKIPPING!!!!\n"); continue; } } /* Write the cert in PEM format to memory */ p_ret = PEM_write_bio_X509( mem, x->x509 ); /* Get the pointer to the memory buffer */ BIO_get_mem_ptr( mem, &mem_buf ); /* Push a PKI_MEM buffer on the stack */ tmp_mem = PKI_MEM_new_null(); PKI_MEM_add ( tmp_mem, mem_buf->data, mem_buf->length); PKI_STACK_push( sk, tmp_mem ); } /* Free the temp memory buffer */ if( mem ) BIO_free( mem ); } else if (strncmp_nocase( url->attrs, "key", 3) == 0 ) { char *pin = NULL; PKI_log_debug("PKCS11::KEY DATATYPE SELECTED!\n"); pin = pkcs11_parse_url_getval( url, "pin" ); if ( (tk->loginRequired == 1) && (pin != NULL ) ) { p_ret = PKCS11_login ( p, 0, pin ); PKI_log_debug("PKCS11::LOGIN Result %d\n", p_ret ); } if((mem = BIO_new(BIO_s_mem())) == NULL ) { goto err; } p_ret = PKCS11_enumerate_keys ( tk, &keyList, &n_objs ); for( n = 0; n < n_objs; n++ ) { key = &keyList[n]; printf("DEBUG::PKCS11::KEY label=%s\n", key->label); printf("DEBUG::PKCS11::KEY id="); for( t = 0; t < key->id_len; t ++ ) { printf("%c", key->id[t] ); } printf("\n"); if( (search_label) && (strncmp_nocase( search_label, x->label, strlen( search_label)) != 0 )){ printf("DEBUG::PKCS11::LABEL does not" "match, SKIPPING!!!!\n"); continue; } if( search_id ) { int stop = 0; for( t = 0; t < x->id_len; t ++ ) { if( search_id[t] != x->id[t] ) { stop = 1; break; } } if( stop == 1 ) { printf("DEBUG::PKCS11::ID does not" "match, SKIPPING!!!!\n"); continue; } } /* Get Private Key in OpenSSL format */ evp_pkey = PKCS11_get_private_key( key ); /* Write the cert in PEM format to memory */ p_ret = PEM_write_bio_PUBKEY( mem, evp_pkey ); /* Get the pointer to the memory buffer */ BIO_get_mem_ptr( mem, &mem_buf ); /* Push a PKI_MEM buffer on the stack */ tmp_mem = PKI_MEM_new_null(); PKI_MEM_add ( tmp_mem, mem_buf->data, mem_buf->length); PKI_STACK_push( sk, tmp_mem ); } if( mem ) BIO_free ( mem ); } else { printf("DEBUG::PKCS11::OTHER DATATYPE SELECTED!\n"); } } err: if( slots ) PKCS11_release_all_slots( ctx, slots, num ); /* if( ctx ) { PKCS11_CTX_unload(ctx); PKCS11_CTX_free(ctx); } */ if( libfile ) PKI_Free (libfile); if( search_slot ) PKI_Free ( search_slot ); if( search_slotid ) PKI_Free ( search_slotid ); if( search_label ) PKI_Free ( search_label ); if( search_id ) PKI_Free ( search_id ); return ( sk ); #else return ( NULL ); #endif }
PKI_MEM_STACK *URL_get_data_mysql_url ( const URL *url, ssize_t size ) { #ifdef HAVE_MYSQL MYSQL_ROW row; MYSQL * sql = NULL; MYSQL_FIELD *fields = NULL; MYSQL_RES *res = NULL; unsigned long *lengths = NULL; long long n_rows = 0; int n_fields = 0; PKI_MEM *tmp_mem = NULL; PKI_MEM_STACK *sk = NULL; char * query = NULL; if( !url ) return (NULL); if((sql = db_connect ( url )) == NULL ) { return NULL; } if ((query = parse_url_query(url)) == NULL) { PKI_log_err("Can not parse URL query"); goto end; } else mysql_query(sql, query); /* Get the Data */ if((res = mysql_store_result( sql )) == NULL) { PKI_log_err("Can not retrieve SQL data"); goto end; } if( ((n_rows = (long long) mysql_num_rows( res )) < 1 ) || ((sk = PKI_STACK_MEM_new()) == NULL)) { PKI_log_err("No returned rows found"); goto end; } while((row = mysql_fetch_row(res)) != NULL ) { /* Count the number of fields retrieved */ n_fields = (int) mysql_num_fields( res ); lengths = mysql_fetch_lengths( res ); fields = mysql_fetch_fields( res ); if (!fields) { PKI_ERROR(PKI_ERR_GENERAL, "can not fetch query fields"); break; } if (n_fields > 0) { tmp_mem = PKI_MEM_new_null(); if (size == 0 || (( size > 0 ) && ( lengths[0] < size))) { PKI_MEM_add(tmp_mem,row[0],lengths[0]); /* For now, let's only deal with one field at the time */ PKI_STACK_push( sk, tmp_mem ); } } } end: if (query) PKI_Free (query); db_close ( sql ); return ( sk ); #else return ( NULL ); #endif }