xmlNodePtr soap_env_get_header(SoapEnv *env) { xmlNodePtr node; if (!env) { log_error1("SoapEnv is NULL"); return NULL; } if (!env->root) { log_error1("SoapEnv contains no document"); return NULL; } for (node = soap_xml_get_children(env->root); node; node = soap_xml_get_next(node)) { if (!xmlStrcmp(node->name, BAD_CAST "Header") && !xmlStrcmp(node->ns->href, BAD_CAST soap_env_ns)) return node; } return NULL; }
char * soap_env_find_methodname(SoapEnv * env) { xmlNodePtr body, node; body = soap_env_get_body(env); if (body == NULL) return 0; node = soap_xml_get_children(body); /* node is the first child */ if (node == NULL) { log_error1("No method found"); return 0; } if (node->name == NULL) { log_error1("No methodname found"); return 0; } return((char *) node->name); }
xmlNodePtr soap_env_get_body(SoapEnv * env) { xmlNodePtr node; if (env == NULL) { log_error1("env object is NULL"); return NULL; } if (env->root == NULL) { log_error1("env has no xml"); return NULL; } for (node = soap_xml_get_children(env->root); node; node = soap_xml_get_next(node)) { if (!xmlStrcmp(node->name, BAD_CAST "Body") && !xmlStrcmp(node->ns->href, BAD_CAST soap_env_ns)) return node; } log_error1("Body tag not found!"); return NULL; }
/* XXX: unused function? */ xmlNodePtr _soap_env_get_body(SoapEnv * env) { xmlNodePtr body; xmlNodeSetPtr nodeset; xmlXPathObjectPtr xpathobj; if (env == NULL) { log_error1("SoapEnv is NULL"); return NULL; } if (env->root == NULL) { log_error1("SoapEnv contains no XML document"); return NULL; } /* find <Body> tag find out namespace xpath: //Envelope/Body/ */ xpathobj = soap_xpath_eval(env->root->doc, "//Envelope/Body"); if (!xpathobj) { log_error1("No Body (xpathobj)!"); return NULL; } if (!(nodeset = xpathobj->nodesetval)) { log_error1("No Body (nodeset)!"); xmlXPathFreeObject(xpathobj); return NULL; } if (nodeset->nodeNr < 1) { log_error1("No Body (nodeNr)!"); xmlXPathFreeObject(xpathobj); return NULL; } body = nodeset->nodeTab[0]; /* body is <Body> */ xmlXPathFreeObject(xpathobj); return body; }
static herror_t _hssl_server_context_init(void) { log_verbose3("enabled=%i, certificate=%p", enabled, certificate); if (!enabled || !certificate) return H_OK; if (!(context = SSL_CTX_new(SSLv23_method()))) { log_error1("Cannot create SSL context"); return herror_new("_hssl_server_context_init", HSSL_ERROR_CONTEXT, "Unable to create SSL context"); } if (!(SSL_CTX_use_certificate_file(context, certificate, SSL_FILETYPE_PEM))) { log_error2("Cannot read certificate file: \"%s\"", certificate); SSL_CTX_free(context); return herror_new("_hssl_server_context_init", HSSL_ERROR_CERTIFICATE, "Unable to use SSL certificate \"%s\"", certificate); } SSL_CTX_set_default_passwd_cb(context, _hssl_password_callback); if (!(SSL_CTX_use_PrivateKey_file(context, certificate, SSL_FILETYPE_PEM))) { log_error2("Cannot read key file: \"%s\"", certificate); SSL_CTX_free(context); return herror_new("_hssl_server_context_init", HSSL_ERROR_PEM, "Unable to use private key"); } if (ca_list != NULL && *ca_list != '\0') { if (!(SSL_CTX_load_verify_locations(context, ca_list, NULL))) { SSL_CTX_free(context); log_error2("Cannot read CA list: \"%s\"", ca_list); return herror_new("_hssl_server_context_init", HSSL_ERROR_CA_LIST, "Unable to read certification authorities \"%s\""); } SSL_CTX_set_client_CA_list(context, SSL_load_client_CA_file(ca_list)); log_verbose1("Certification authority contacted"); } SSL_CTX_set_verify(context, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, _hssl_cert_verify_callback); log_verbose1("Certificate verification callback registered"); SSL_CTX_set_mode(context, SSL_MODE_AUTO_RETRY); SSL_CTX_set_session_cache_mode(context, SSL_SESS_CACHE_OFF); _hssl_superseed(); return H_OK; }
herror_t soap_env_new_from_doc(xmlDocPtr doc, SoapEnv ** out) { xmlNodePtr node; SoapEnv *env; if (doc == NULL) { log_error1("Can not create xml document!"); return herror_new("soap_env_new_from_doc", GENERAL_INVALID_PARAM, "XML Document (xmlDocPtr) is NULL"); } if (!(node = xmlDocGetRootElement(doc))) { log_error1("XML document is empty!"); return herror_new("soap_env_new_from_doc", XML_ERROR_EMPTY_DOCUMENT, "XML Document is empty!"); } if (!(env = (SoapEnv *) malloc(sizeof(SoapEnv)))) { log_error2("malloc failed (%s)", strerror(errno)); return herror_new("soap_env_from_doc", GENERAL_INVALID_PARAM, "malloc failed"); } env->root = node; env->header = soap_env_get_header(env); env->body = soap_env_get_body(env); env->cur = soap_env_get_method(env); *out = env; return H_OK; }
herror_t hssl_server_ssl(hsocket_t * sock) { SSL *ssl; int ret; BIO *sbio; if (!enabled) return H_OK; log_verbose2("Starting SSL initialization for socket %d", sock->sock); if (!(ssl = SSL_new(context))) { log_warn1("SSL_new failed"); return herror_new("hssl_server_ssl", HSSL_ERROR_SERVER, "Cannot create SSL object"); } /* SSL_set_fd(ssl, sock->sock); */ sbio = BIO_new_socket(sock->sock, BIO_NOCLOSE); if (sbio == NULL) { log_error1("BIO_new_socket failed"); return NULL; } // BIO_set_callback(sbio, hssl_bio_cb); sbio->method->bread = _hssl_bio_read; SSL_set_bio(ssl, sbio, sbio); if ((ret = SSL_accept(ssl)) <= 0) { herror_t err; log_error2("SSL_accept failed (%s)", _hssl_get_error(ssl, ret)); err = herror_new("hssl_server_ssl", HSSL_ERROR_SERVER, "SSL_accept failed (%s)", _hssl_get_error(ssl, ret)); SSL_free(ssl); return err; } sock->ssl = ssl; return H_OK; }
xmlNodePtr soap_env_add_item(SoapEnv * call, const char *type, const char *name, const char *value) { xmlNodePtr newnode; newnode = xmlNewTextChild(call->cur, NULL, BAD_CAST name, BAD_CAST value); if (newnode == NULL) { log_error1("Can not create new xml node"); return NULL; } if (type) { if (!xmlNewProp(newnode, BAD_CAST "xsi:type", BAD_CAST type)) { log_error1("Can not create new xml attribute"); return NULL; } } return newnode; }
static void hurl_dump(const hurl_t * url) { if (url == NULL) { log_error1("url is NULL!"); return; } log_verbose2("PROTOCOL : %d", url->protocol); log_verbose2(" HOST : %s", url->host); log_verbose2(" PORT : %d", url->port); log_verbose2(" CONTEXT : %s", url->context); }
xmlNodePtr soap_env_add_attachment(SoapEnv * call, const char *name, const char *href) { xmlNodePtr newnode; newnode = xmlNewTextChild(call->cur, NULL, BAD_CAST name, BAD_CAST ""); if (newnode == NULL) { log_error1("Can not create new xml node"); return NULL; } if (href) { if (!xmlNewProp(newnode, BAD_CAST "href", BAD_CAST href)) { log_error1("Can not create new xml attribute"); return NULL; } } return newnode; }
herror_t hssl_client_ssl(hsocket_t * sock) { SSL *ssl; int ret; log_verbose1("Starting SSL client initialization"); if (!(ssl = SSL_new(context))) { log_error1("Cannot create new SSL object"); return herror_new("hssl_client_ssl", HSSL_ERROR_CLIENT, "SSL_new failed"); } SSL_set_fd(ssl, sock->sock); if ((ret = SSL_connect(ssl)) <= 0) { herror_t err; log_error2("SSL connect error (%s)", _hssl_get_error(ssl, -1)); err = herror_new("hssl_client_ssl", HSSL_ERROR_CONNECT, "SSL_connect failed (%s)", _hssl_get_error(ssl, ret)); SSL_free(ssl); return err; } /* SSL_connect should take care of this for us. if (SSL_get_peer_certificate(ssl) == NULL) { log_error1("No certificate provided"); SSL_free(ssl); return herror_new("hssl_client_ssl", HSSL_ERROR_CERTIFICATE, "No certificate provided"); } if (SSL_get_verify_result(ssl) != X509_V_OK) { log_error1("Certificate did not verify"); SSL_free(ssl); return herror_new("hssl_client_ssl", HSSL_ERROR_CERTIFICATE, "Verfiy certificate failed"); } */ log_verbose1("SSL client initialization completed"); sock->ssl = ssl; return H_OK; }
char * hpairnode_get(hpair_t * pair, const char *key) { if (key == NULL) { log_error1("key is NULL"); return NULL; } while (pair != NULL) { if (pair->key != NULL) { if (!strcmp(pair->key, key)) { return pair->value; } } pair = pair->next; } return NULL; }
char * soap_env_find_urn(SoapEnv * env) { xmlNsPtr ns; xmlNodePtr body, node; if (!(body = soap_env_get_body(env))) { log_verbose1("body is NULL"); return 0; } /* node is the first child */ if (!(node = soap_xml_get_children(body))) { log_error1("No namespace found"); return 0; } /* if (node->ns && node->ns->prefix) MRC 1/25/2006 */ if (node->ns) { ns = xmlSearchNs(body->doc, node, node->ns->prefix); if (ns != NULL) { return((char *) ns->href); /* namespace found! */ } } else { static char *empty = ""; log_warn1("No namespace found"); return(empty); } return 0; }
void *reader_thread(void *arg) { SoapCtx *ctx, *ctx2; xmlNodePtr xmlcur,xmlitem,xmlitem2; herror_t err; char *itemname,*itemvalue,buf[1024], *cptr; int ret; THREAD_PARAM *p = (THREAD_PARAM *) arg; const char *url = (const char *) p->user; rlMailbox rlmbx(mbx); // read mbx until it is empty rlmbx.clear(); printf("reader_thread starting\n"); // wait for commands from clients while(1) { ret = rlmbx.read(buf,sizeof(buf)); // read "itemname,itemvalue\n" if(ret <= 0) continue; itemname = itemvalue = &buf[0]; cptr = strchr(buf,','); if(cptr != NULL) { *cptr = '\0'; cptr++; itemvalue = cptr; cptr = strchr(itemvalue,'\n'); if(cptr != NULL) *cptr = 0; } if(debug) { printf("reader_thread Write itemname=%s itemvalue=%s\n",itemname,itemvalue); } p->thread->lock(); /* create a SoapCtx object */ err = soap_ctx_new_with_method(URN, "Write", &ctx); if (err != H_OK) { log_error4("%s():%s [%d]", herror_func(err), herror_message(err), herror_code(err)); herror_release(err); goto end_of_while; } /* create the ItemList */ xmlitem = soap_env_add_item(ctx->env, "xsd:element", "ItemList", ""); xmlcur = ctx->env->cur; ctx->env->cur = xmlitem; xmlitem2 = soap_env_add_item(ctx->env, "xsd:string", "Items", NULL); if (!xmlNewProp(xmlitem2, BAD_CAST "ItemName", BAD_CAST itemname)) { log_error1("Can not create new xml attribute ItemName"); goto end_of_while; } ctx->env->cur = xmlitem2; if(isdigit(itemvalue[0])) { soap_env_add_item(ctx->env,"xsd:double","Value",itemvalue); } else if(strcmp(itemvalue, "true") == 0 || strcmp(itemvalue, "false") == 0) { soap_env_add_item(ctx->env, "xsd:boolean", "Value", itemvalue); } else { soap_env_add_item(ctx->env,"xsd:istring","Value",itemvalue); } ctx->env->cur = xmlitem; ctx->env->cur = xmlcur; /* invoke */ err = soap_client_invoke(ctx, &ctx2, url, ""); if (err != H_OK) { log_error4("[%d] %s(): %s ", herror_code(err), herror_func(err), herror_message(err)); herror_release(err); soap_ctx_free(ctx); goto end_of_while; } /* print the result */ if(debug) { printf("reader_thread result:\n"); soap_xml_doc_print(ctx2->env->root->doc); } end_of_while: /* free the objects */ soap_ctx_free(ctx2); soap_ctx_free(ctx); p->thread->unlock(); } return NULL; }
herror_t mime_get_attachments(content_type_t * ctype, http_input_stream_t * in, attachments_t ** dest) { /* MIME variables */ attachments_t *mimeMessage; part_t *part, *tmp_part = NULL; char *boundary, *root_id; /* Check for MIME message */ if (!(ctype && !strcmp(ctype->type, "multipart/related"))) return herror_new("mime_get_attachments", MIME_ERROR_NOT_MIME_MESSAGE, "Not a MIME message '%s'", ctype->type); boundary = hpairnode_get(ctype->params, "boundary"); root_id = hpairnode_get(ctype->params, "start"); if (boundary == NULL) { /* TODO (#1#): Handle Error in http form */ log_error1("'boundary' not set for multipart/related"); return herror_new("mime_get_attachments", MIME_ERROR_NO_BOUNDARY_PARAM, "'boundary' not set for multipart/related"); } if (root_id == NULL) { /* TODO (#1#): Handle Error in http form */ log_error1("'start' not set for multipart/related"); return herror_new("mime_get_attachments", MIME_ERROR_NO_START_PARAM, "'start' not set for multipart/related"); } mimeMessage = mime_message_parse(in, root_id, boundary, "."); if (mimeMessage == NULL) { /* TODO (#1#): Handle Error in http form */ log_error1("MIME Parse Error"); return herror_new("mime_get_attachments", MIME_ERROR_PARSE_ERROR, "MIME Parse Error"); } /* Find root */ if (!mimeMessage->root_part) { attachments_free(mimeMessage); return herror_new("mime_get_attachments", MIME_ERROR_NO_ROOT_PART, "No root part found!"); } /* delete root_part from list */ part = mimeMessage->parts; while (part) { if (part == mimeMessage->root_part) { if (tmp_part) tmp_part->next = part->next; else mimeMessage->parts = part->next; break; } tmp_part = part; part = part->next; } *dest = mimeMessage; return H_OK; }
static void _mime_received_bytes(void *data, const unsigned char *bytes, int size) { int i = 0; char *id, *type, *location; mime_callback_data_t *cbdata = (mime_callback_data_t *) data; if (!cbdata) { log_error1 ("MIME transport error Called <received bytes> without initializing\n"); return; } if (!cbdata->current_part) { log_error1 ("MIME transport error Called <received bytes> without initializing\n"); return; } /* log_verbose4("Received %d bytes (%p), header_search = %d", size, data, cbdata->header_search); */ if (cbdata->header_search < 4) { /* Find \r\n\r\n in bytes */ for (i = 0; i < size; i++) { if (cbdata->header_search == 0) { if (bytes[i] == '\r') cbdata->header_search++; else { cbdata->header[cbdata->header_index++] = bytes[i]; cbdata->header_search = 0; } } else if (cbdata->header_search == 1) { if (bytes[i] == '\n') cbdata->header_search++; else { cbdata->header[cbdata->header_index++] = '\r'; cbdata->header[cbdata->header_index++] = bytes[i]; cbdata->header_search = 0; } } else if (cbdata->header_search == 2) { if (bytes[i] == '\r') cbdata->header_search++; else { cbdata->header[cbdata->header_index++] = '\r'; cbdata->header[cbdata->header_index++] = '\n'; cbdata->header[cbdata->header_index++] = bytes[i]; cbdata->header_search = 0; } } else if (cbdata->header_search == 3) { if (bytes[i] == '\n') { cbdata->header[cbdata->header_index++] = '\r'; cbdata->header[cbdata->header_index++] = '\n'; cbdata->header[cbdata->header_index++] = '\0'; cbdata->header_search = 4; cbdata->current_part->header = _mime_process_header(cbdata->header); hpairnode_dump_deep(cbdata->current_part->header); /* set id */ id = hpairnode_get(cbdata->current_part->header, HEADER_CONTENT_ID); if (id != NULL) { strcpy(cbdata->current_part->id, id); if (!strcmp(id, cbdata->root_id)) cbdata->message->root_part = cbdata->current_part; } location = hpairnode_get(cbdata->current_part->header, HEADER_CONTENT_LOCATION); if (location != NULL) { strcpy(cbdata->current_part->location, location); } type = hpairnode_get(cbdata->current_part->header, HEADER_CONTENT_TYPE); if (type != NULL) { strcpy(cbdata->current_part->content_type, type); } i++; break; } else { cbdata->header[cbdata->header_index++] = '\r'; cbdata->header[cbdata->header_index++] = '\n'; cbdata->header[cbdata->header_index++] = '\r'; cbdata->header[cbdata->header_index++] = bytes[i]; cbdata->header_search = 0; } } /* TODO (#1#): Check for cbdata->header overflow */ } /* for (i=0;i<size;i++) */ } /* if (cbdata->header_search < 4) */ if (i >= size - 1) return; /* Write remaining bytes into the file or buffer (if root) (buffer is disabled in this version) */ if (cbdata->current_fd) fwrite(&(bytes[i]), 1, size - i, cbdata->current_fd); }
herror_t hurl_parse(hurl_t * url, const char *urlstr) { int iprotocol; int ihost; int iport; int len; int size; char tmp[8]; char protocol[1024]; iprotocol = 0; len = strlen(urlstr); /* find protocol */ while (urlstr[iprotocol] != ':' && urlstr[iprotocol] != '\0') { iprotocol++; } if (iprotocol == 0) { log_error1("no protocol"); return herror_new("hurl_parse", URL_ERROR_NO_PROTOCOL, "No protocol"); } if (iprotocol + 3 >= len) { log_error1("no host"); return herror_new("hurl_parse", URL_ERROR_NO_HOST, "No host"); } if (urlstr[iprotocol] != ':' && urlstr[iprotocol + 1] != '/' && urlstr[iprotocol + 2] != '/') { log_error1("no protocol"); return herror_new("hurl_parse", URL_ERROR_NO_PROTOCOL, "No protocol"); } /* find host */ ihost = iprotocol + 3; while (urlstr[ihost] != ':' && urlstr[ihost] != '/' && urlstr[ihost] != '\0') { ihost++; } if (ihost == iprotocol + 1) { log_error1("no host"); return herror_new("hurl_parse", URL_ERROR_NO_HOST, "No host"); } /* find port */ iport = ihost; if (ihost + 1 < len) { if (urlstr[ihost] == ':') { while (urlstr[iport] != '/' && urlstr[iport] != '\0') { iport++; } } } /* find protocol */ strncpy(protocol, urlstr, iprotocol); protocol[iprotocol] = '\0'; if (strcmpigcase(protocol, "http")) url->protocol = PROTOCOL_HTTP; else if (strcmpigcase(protocol, "https")) url->protocol = PROTOCOL_HTTPS; else if (strcmpigcase(protocol, "ftp")) url->protocol = PROTOCOL_FTP; else return herror_new("hurl_parse", URL_ERROR_UNKNOWN_PROTOCOL, "Unknown protocol '%s'", protocol); /* TODO (#1#): add max of size and URL_MAX_HOST_SIZE */ size = ihost - iprotocol - 3; strncpy(url->host, &urlstr[iprotocol + 3], size); url->host[size] = '\0'; if (iport > ihost) { size = iport - ihost; strncpy(tmp, &urlstr[ihost + 1], size); url->port = atoi(tmp); } else { switch (url->protocol) { case PROTOCOL_HTTP: url->port = URL_DEFAULT_PORT_HTTP; break; case PROTOCOL_HTTPS: url->port = URL_DEFAULT_PORT_HTTPS; break; case PROTOCOL_FTP: url->port = URL_DEFAULT_PORT_FTP; break; } } len = strlen(urlstr); if (len > iport) { /* TODO (#1#): find max of size and URL_MAX_CONTEXT_SIZE */ size = len - iport; strncpy(url->context, &urlstr[iport], size); url->context[size] = '\0'; } else { url->context[0] = '\0'; } hurl_dump(url); return H_OK; }
/*-------------------------------------------------- FUNCTION: httpc_talk_to_server DESC: This function is the heart of the httpc module. It will send the request and process the response. Here the parameters: method: the request method. This can be HTTP_REQUEST_POST and HTTP_REQUEST_GET. conn: the connection object (created with httpc_new()) urlstr: the complete url in string format. http://<host>:<port>/<context> where <port> is not mendatory. start_cb: a callback function, which will be called when the response header is completely arrives. cb: a callback function, which will be called everytime when data arrives. content_size: size of content to send. (only if method is HTTP_REQUEST_POST) content: the content data to send. (only if method is HTTP_REQUEST_POST) userdata: a user define data, which will be passed to the start_cb and cb callbacks as a parameter. This can also be NULL. If success, this function will return 0. >0 otherwise. ----------------------------------------------------*/ static herror_t httpc_talk_to_server(hreq_method_t method, httpc_conn_t * conn, const char *urlstr) { hurl_t url; char buffer[4096]; herror_t status; int ssl; if (conn == NULL) { return herror_new("httpc_talk_to_server", GENERAL_INVALID_PARAM, "httpc_conn_t param is NULL"); } /* Build request header */ httpc_header_set_date(conn); if ((status = hurl_parse(&url, urlstr)) != H_OK) { log_error2("Can not parse URL '%s'", SAVE_STR(urlstr)); return status; } /* TODO (#1#): Check for HTTP protocol in URL */ /* Set hostname */ httpc_set_header(conn, HEADER_HOST, url.host); ssl = url.protocol == PROTOCOL_HTTPS ? 1 : 0; /* Open connection */ if ((status = hsocket_open(&conn->sock, url.host, url.port, ssl)) != H_OK) return status; switch(method) { case HTTP_REQUEST_GET: sprintf(buffer, "GET %s HTTP/%s\r\n", (url.context[0] != '\0') ? url.context : ("/"), (conn->version == HTTP_1_0) ? "1.0" : "1.1"); break; case HTTP_REQUEST_POST: sprintf(buffer, "POST %s HTTP/%s\r\n", (url.context[0] != '\0') ? url.context : ("/"), (conn->version == HTTP_1_0) ? "1.0" : "1.1"); break; default: log_error1("Unknown method type!"); return herror_new("httpc_talk_to_server", GENERAL_INVALID_PARAM, "hreq_method_t must be HTTP_REQUEST_GET or HTTP_REQUEST_POST"); } log_verbose1("Sending request..."); if ((status = hsocket_send(&(conn->sock), buffer)) != H_OK) { log_error2("Cannot send request (%s)", herror_message(status)); hsocket_close(&(conn->sock)); return status; } log_verbose1("Sending header..."); if ((status = httpc_send_header(conn)) != H_OK) { log_error2("Cannot send header (%s)", herror_message(status)); hsocket_close(&(conn->sock)); return status; } return H_OK; }