int ssh_cm_render_crl(unsigned char *buf, int len, int precision, void *datum) { SshX509Crl crl = datum; char *name; SshBerTimeStruct this_update, next_update; SshBufferStruct buffer; if (crl) { ssh_buffer_init(&buffer); ssh_buffer_append_str(&buffer, "\ncrl = { \n"); if (!ssh_x509_crl_get_issuer_name(crl, &name)) { ssh_buffer_append_str(&buffer, " missing-issuer-name\n"); } else { ssh_buffer_append_cstrs(&buffer, " issuer-name = <", name, ">\n", NULL); ssh_free(name); } if (!ssh_x509_crl_get_update_times(crl, &this_update, &next_update)) { ssh_buffer_append_str(&buffer, " missing-update-times\n"); } else { if (ssh_ber_time_available(&this_update)) { ssh_ber_time_to_string(&this_update, &name); ssh_buffer_append_cstrs(&buffer, " this-update = ", name, "\n", NULL); ssh_free(name); } if (ssh_ber_time_available(&next_update)) { ssh_ber_time_to_string(&next_update, &name); ssh_buffer_append_cstrs(&buffer, " next-update = ", name, "\n", NULL); ssh_free(name); } } /* Finished. */ ssh_buffer_append_str(&buffer, "}\n"); return cm_debug_renderer_return(&buffer, buf, len); } return 0; }
int ssh_cm_render_state(unsigned char *buf, int len, int precision, void *datum) { SshCMSearchState state = *(unsigned int *)((void *)&datum); int i; const char *name; SshBufferStruct buffer; ssh_buffer_init(&buffer); ssh_buffer_append_str(&buffer, "\nsearch-state = \n{\n"); if (state == 0) ssh_buffer_append_str(&buffer, " nil\n"); else { for (i = 0; i < 32; i++) { if (state & (1 << i)) { name = ssh_find_keyword_name(ssh_cm_debug_state_strs, (1 << i)); ssh_buffer_append_cstrs(&buffer, " ", name, "\n", NULL); } } } ssh_buffer_append_str(&buffer, "}\n"); return cm_debug_renderer_return(&buffer, buf, len); }
static Boolean catch_handler(SshHttpServerContext ctx, SshHttpServerConnection conn, SshStream stream, void *context) { SshBuffer data = ssh_buffer_allocate(); ssh_buffer_append_cstrs(data, "<body><h1>ProxyFilter Update Wizard</h1>\n", NULL); ssh_http_server_send_buffer(conn, data); return TRUE; }
/* * Inserts specified event into log file specified in context. * event parameter specifies the audited event. Each element after event * must start with a SshAuditformat type followed by arguments of the * appropriate type, and the list must end with SSH_AUDIT_ARGUMENT_END. */ void ssh_audit_event(SshAuditContext context, SshAuditEvent event, ...) { size_t bytes; va_list ap; SshBuffer *audit_info, *formated_str; char *audit_time; if (context == NULL) return; if ((event < 0) || (event > SSH_AUDIT_MAX_VALUE)) return; /* Check if given event is allowed */ if (!context->ssh_audit_event_allowed[(int)event]) return; /* Initialize a buffer for output string */ audit_info = ssh_buffer_allocate(); /* Start constructing string which will be inserted into audit log.*/ /* Start with inserting the name of the event.*/ /* then date and time */ audit_time = ssh_time_string(ssh_time()); ssh_buffer_append_cstrs(audit_info, ssh_find_keyword_name(ssh_audit_event_title, (int)event), ": ", audit_time, ": ", NULL); ssh_xfree(audit_time); /* Handle the variable list*/ va_start(ap, event); formated_str = ssh_format_audit_string(ap); va_end(ap); /* Insert given parameters into string*/ ssh_buffer_append(audit_info, ssh_buffer_ptr(formated_str), ssh_buffer_len(formated_str)); ssh_buffer_append(audit_info, (unsigned char *) "\0", 1); /* Output the log message*/ ssh_send_log_message(context, ssh_buffer_ptr(audit_info)); ssh_buffer_free(formated_str); ssh_buffer_free(audit_info); }
static void filter_html(SshBuffer to, SshBuffer from, Boolean eof_seen, void *context) { ProxyRequest *req = context; unsigned char *cp; size_t len; size_t i; restart: cp = ssh_buffer_ptr(from); len = ssh_buffer_len(from); for (i = 0; i < len; i++) { switch (req->state) { case FILTER_TEXT: if (cp[i] == '<') { ssh_buffer_append(to, cp, i); ssh_buffer_consume(from, i); len = ssh_buffer_len(from); cp = ssh_buffer_ptr(from); /* Is the end of the tag seen? */ for (i = 0; i < len; i++) if (cp[i] == '>') { i++; break; } if (i >= len && !eof_seen) /* No, need more data. */ return; /* Yes, it is seen. */ if (i > 4 && strncasecmp(cp, "<img", 4) == 0) { char *url = parse_img_src(cp, i); ssh_buffer_append_cstrs(to, "<a href=\"http://amme.ssh.fi:8080", "/catch?url=", url, "\">*</a>", NULL); } ssh_buffer_append(to, cp, i); ssh_buffer_consume(from, i); goto restart; } else if (cp[i] == '&') req->state = FILTER_ENTITY; break; case FILTER_ENTITY: if (cp[i] == ';') req->state = FILTER_TEXT; break; } } ssh_buffer_append(to, ssh_buffer_ptr(from), ssh_buffer_len(from)); ssh_buffer_clear(from); }
static void result_callback(SshHttpClientContext ctx, SshHttpResult result, SshTcpError ip_error, SshStream stream, void *callback_context) { ProxyRequest *req = callback_context; SshBuffer error; char buf[256]; switch (result) { case SSH_HTTP_RESULT_SUCCESS: { const char *value = NULL; SshCopyStreamCopyCb copy_cb = copy_data; if ((value = ssh_http_get_header_field(ctx, "Content-Type"))) ssh_http_server_set_values(req->conn, SSH_HTTP_HDR_FIELD, "Content-Type", value, SSH_HTTP_HDR_END); req->client_stream = stream; #if SMART_UPDATE if (value && strncmp(value, "text/html", 9) == 0) copy_cb = filter_html; #endif ssh_copy_stream(req->server_stream, req->client_stream, copy_cb, req_finish, req); } break; case SSH_HTTP_RESULT_MALFORMED_URL: error = ssh_buffer_allocate(); ssh_buffer_append_cstrs(error, "<body><h1>Malformed URL</h1>n", NULL); ssh_http_server_send_buffer(req->conn, error); ssh_xfree(req); break; case SSH_HTTP_RESULT_REDIRECT_LIMIT_EXCEEDED: { const char *location = ssh_http_get_header_field(ctx, "Location"); const char *reason_phrase; SSH_DEBUG(SSH_D_HIGHSTART, ("Redirect: %s", location)); ssh_http_server_error(req->conn, ssh_http_get_status_code(ctx, &reason_phrase), SSH_HTTP_HDR_LOCATION, location, SSH_HTTP_HDR_END); ssh_stream_destroy(req->server_stream); ssh_xfree(req); } break; case SSH_HTTP_RESULT_HTTP_ERROR: { const char *reason_phrase; SshUInt32 error_code; error_code = ssh_http_get_status_code(ctx, &reason_phrase); error = ssh_buffer_allocate(); ssh_snprintf(buf, sizeof(buf), "%ld", error_code); ssh_http_server_error(req->conn, error_code, SSH_HTTP_HDR_END); ssh_buffer_append_cstrs(error, "<body><h1>HTTP Error (", buf, ")</h1>\n<pre>\n", reason_phrase, "\n", NULL); ssh_http_server_send_buffer(req->conn, error); ssh_xfree(req); } break; default: error = ssh_buffer_allocate(); ssh_snprintf(buf, sizeof(buf), "%d", result); ssh_buffer_append_cstrs(error, "<body><h1>HTTP Library Error ", buf, "</h1>\n", NULL); ssh_http_server_send_buffer(req->conn, error); ssh_xfree(req); break; } }
/* The URI handler. */ static Boolean proxy_handler(SshHttpServerContext ctx, SshHttpServerConnection conn, SshStream stream, void *context) { const char *method = ssh_http_server_get_method(conn); const char *uri = ssh_http_server_get_uri(conn); SshHttpClientParams params; ProxyRequest *req; SshBuffer error; ProxyCensor *c; SSH_DEBUG(SSH_D_HIGHSTART, ("method=%s, uri=%s", method, uri)); for (c = censor; c; c = c->next) if (ssh_match_pattern(uri, c->pattern)) { SSH_DEBUG(SSH_D_HIGHSTART, ("censored by pattern `%s'", c->pattern)); ssh_http_server_error(conn, 301, SSH_HTTP_HDR_LOCATION, "http://people.ssh.fi/mtr/censor.jpg", SSH_HTTP_HDR_FIELD, "Content-Type", "text/html", SSH_HTTP_HDR_END); ssh_stream_destroy(stream); return TRUE; } memset(¶ms, 0, sizeof(params)); params.http_proxy_url = proxy_url; params.num_redirections = 0; req = ssh_xcalloc(1, sizeof(*req)); req->server = ctx; req->conn = conn; req->server_stream = stream; req->client = ssh_http_client_init(¶ms); if (strcmp(method, "GET") == 0) ssh_http_get(req->client, uri, result_callback, req, SSH_HTTP_HDR_END); else if (strcmp(method, "HEAD") == 0) ssh_http_head(req->client, uri, result_callback, req, SSH_HTTP_HDR_END); else if (strcmp(method, "POST") == 0 || strcmp(method, "PUT") == 0) { SSH_DEBUG(SSH_D_ERROR, ("%s not implemented yet", method)); ssh_xfree(req); error = ssh_buffer_allocate(); ssh_buffer_append_cstrs(error, "<body><h1>Method `", method, "' not implemented yet</h1>\n", NULL); ssh_http_server_send_buffer(conn, error); } else { SSH_DEBUG(SSH_D_ERROR, ("unknown method `%s'", method)); ssh_xfree(req); error = ssh_buffer_allocate(); ssh_buffer_append_cstrs(error, "<body><h1>Unknown method `", method, "'</h1>\n", NULL); ssh_http_server_send_buffer(conn, error); } return TRUE; }
int ssh_cm_render_certificate(unsigned char *buf, int len, int precision, void *datum) { SshX509Certificate cert = datum; char *name; unsigned char *t; SshX509Name names; SshMPIntegerStruct mp; SshBerTimeStruct not_before, not_after; SshBufferStruct buffer; SshX509OidList oid_list; const SshOidStruct *oids; Boolean critical; SshStr str; size_t l, kid_len; SshPublicKey pub; unsigned char *kid; if (cert) { ssh_buffer_init(&buffer); ssh_buffer_append_str(&buffer, "\ncertificate = { \n"); /* Add the serial number. */ ssh_mprz_init(&mp); if (ssh_x509_cert_get_serial_number(cert, &mp) == FALSE) { ssh_buffer_append_str(&buffer, " missing-serial-number\n"); } else { if ((t = (unsigned char *) ssh_mprz_get_str(&mp, 10)) != NULL) { ssh_buffer_append_cstrs(&buffer, " serial-number = ", t, "\n", NULL); ssh_mprz_clear(&mp); ssh_free(t); } else { ssh_mprz_clear(&mp); ssh_buffer_uninit(&buffer); return -1; } } /* Add suitable names. */ ssh_x509_name_reset(cert->subject_name); if (!ssh_x509_cert_get_subject_name_str(cert, &str)) { ssh_buffer_append_str(&buffer, " missing-subject-name\n"); } else { SshStr latin1 = ssh_str_charset_convert(str, SSH_CHARSET_ISO_8859_1); name = (char *)ssh_str_get(latin1, &l); ssh_buffer_append_cstrs(&buffer, " subject-name = <", name, ">\n", NULL); ssh_str_free(latin1); ssh_free(name); ssh_str_free(str); } ssh_x509_name_reset(cert->issuer_name); if (!ssh_x509_cert_get_issuer_name(cert, &name)) { ssh_buffer_append_str(&buffer, " missing-issuer-name\n"); } else { ssh_buffer_append_cstrs(&buffer, " issuer-name = <", name, ">\n", NULL); ssh_free(name); } /* Validity period. */ if (!ssh_x509_cert_get_validity(cert, ¬_before, ¬_after)) { ssh_buffer_append_str(&buffer, " missing-validity-period\n"); } else { if ((t = ssh_malloc(64)) != NULL) { if (ssh_ber_time_available(¬_before)) { ssh_snprintf(t, 64, "%@", ssh_ber_time_render, ¬_before); ssh_buffer_append_cstrs(&buffer, " not-before = ", t, "\n", NULL); } if (ssh_ber_time_available(¬_after)) { ssh_snprintf(t, 64, "%@", ssh_ber_time_render, ¬_after); ssh_buffer_append_cstrs(&buffer, " not-after = ", t, "\n", NULL); } ssh_free(t); } } if (ssh_x509_cert_get_subject_key_id(cert, &kid, &kid_len, &critical)) { unsigned char *fingerprint; if ((fingerprint = (unsigned char *) ssh_fingerprint(kid, kid_len, SSH_FINGERPRINT_HEX_UPPER)) != NULL) ssh_buffer_append_cstrs(&buffer, " subject-kid = ", fingerprint, "\n", NULL); ssh_free(fingerprint); } if (ssh_x509_cert_get_public_key(cert, &pub)) { unsigned char *key_digest; size_t digest_len; if (ssh_cm_key_kid_create(pub, FALSE, &key_digest, &digest_len)) { unsigned char *fingerprint; fingerprint = (unsigned char *)ssh_fingerprint(key_digest, digest_len, SSH_FINGERPRINT_HEX_UPPER); if (fingerprint) { ssh_buffer_append_cstrs(&buffer, " pubkey-hash = ", ssh_sstr(fingerprint), "\n", NULL); } ssh_free(fingerprint); ssh_free(key_digest); } ssh_public_key_free(pub); } /* Some alternate names. */ if (ssh_x509_cert_get_subject_alternative_names(cert, &names, &critical)) { ssh_x509_name_reset(names); ssh_buffer_append_str(&buffer, " subject-alt-names = { \n"); ssh_cm_names_dump(&buffer, names); ssh_buffer_append_str(&buffer, " }\n"); } if (ssh_x509_cert_get_issuer_alternative_names(cert, &names, &critical)) { ssh_x509_name_reset(names); ssh_buffer_append_str(&buffer, " issuer-alt-names = { \n"); ssh_cm_names_dump(&buffer, names); ssh_buffer_append_str(&buffer, " }\n"); } if (ssh_x509_cert_get_ext_key_usage(cert, &oid_list, &critical)) { ssh_buffer_append_str(&buffer, " extended-key-usage = { \n"); while (oid_list != NULL) { oids = ssh_oid_find_by_oid_of_type(ssh_custr(oid_list->oid), SSH_OID_EXT_KEY_USAGE); if (oids == NULL) ssh_buffer_append_cstrs(&buffer, " (", oid_list->oid, ")\n", NULL); else ssh_buffer_append_cstrs(&buffer, " ", oids->std_name, " (", oid_list->oid, ")\n", NULL); oid_list = oid_list->next; } ssh_buffer_append_str(&buffer, " }\n"); } ssh_buffer_append_str(&buffer, "}\n"); return cm_debug_renderer_return(&buffer, buf, len); } return 0; }
/* Debug stuff. */ void ssh_buffer_append_str(SshBuffer buffer, char *str) { ssh_buffer_append_cstrs(buffer, str, NULL); }
static void ssh_cm_names_dump(SshBuffer buffer, SshX509Name names) { char *name; unsigned char tmp_str[512]; unsigned char *buf; size_t buf_len; while (ssh_x509_name_pop_ip(names, &buf, &buf_len)) { if (buf_len == 4) ssh_snprintf(tmp_str, sizeof(tmp_str), "%d.%d.%d.%d", (int)buf[0], (int)buf[1], (int)buf[2], (int)buf[3]); else { size_t len; int i; len = 0; for (i = 0; i < buf_len; i++) { ssh_snprintf(tmp_str + len, sizeof(tmp_str) - len, "%02x", buf[i]); len += ssh_ustrlen(tmp_str + len); if (i != buf_len - 1 && (i & 0x1) == 1) { ssh_snprintf(tmp_str + len, sizeof(tmp_str) - len, ":"); len++; } } } ssh_buffer_append_str(buffer, " ip = "); ssh_buffer_append_cstrs(buffer, tmp_str, NULL); ssh_buffer_append_str(buffer, "\n"); ssh_free(buf); } while (ssh_x509_name_pop_dns(names, &name)) { ssh_buffer_append_str(buffer, " dns = "); ssh_buffer_append_str(buffer, name); ssh_buffer_append_str(buffer, "\n"); ssh_free(name); } while (ssh_x509_name_pop_uri(names, &name)) { ssh_buffer_append_str(buffer, " uri = "); ssh_buffer_append_str(buffer, name); ssh_buffer_append_str(buffer, "\n"); ssh_free(name); } while (ssh_x509_name_pop_email(names, &name)) { ssh_buffer_append_str(buffer, " email = "); ssh_buffer_append_str(buffer, name); ssh_buffer_append_str(buffer, "\n"); ssh_free(name); } while (ssh_x509_name_pop_rid(names, &name)) { ssh_buffer_append_str(buffer, " rid = "); ssh_buffer_append_str(buffer, name); ssh_buffer_append_str(buffer, "\n"); ssh_free(name); } while (ssh_x509_name_pop_directory_name(names, &name)) { ssh_buffer_append_str(buffer, " directory-name = <"); ssh_buffer_append_str(buffer, name); ssh_buffer_append_str(buffer, ">\n"); ssh_free(name); } }
/* * Formats string that is being writen to the log file. Function gets its * information in variable-length argument list. Each element must start with * a SshAuditformat type followed by arguments of the appropriate type. * The list must end with SSH_AUDIT_ARGUMENT_END. * Function returns buffer containing the constructed string. * NOTE: Returned buffer MUST be released by the calling function! */ SshBuffer *ssh_format_audit_string(va_list ap) { SshAuditArgument format; char s[128]; SshBuffer *result; SshUInt32 size; unsigned char *i; result = ssh_buffer_allocate(); for (;;) { format = va_arg(ap, SshAuditArgument); switch (format) { case SSH_AUDIT_SPI: i = va_arg(ap, unsigned char *); size = va_arg(ap, size_t); if (i == NULL || size == 0) break; ssh_bin_to_hex_str(s, size, i); ssh_buffer_append_cstrs(result, " SPI:0x", s, NULL); break; case SSH_AUDIT_SOURCE_ADDRESS: i = va_arg(ap, unsigned char *); size = va_arg(ap, size_t); if (i == NULL || size == 0) break; if (size == 4) ssh_audit_v4tostr(s, sizeof(s), i); else ssh_audit_v6tostr(s, sizeof(s), i); ssh_buffer_append_cstrs(result, " Source addr:", s, NULL); break; case SSH_AUDIT_DESTINATION_ADDRESS: i = va_arg(ap, unsigned char *); size = va_arg(ap, size_t); if (i == NULL || size == 0) break; if (size == 4) ssh_audit_v4tostr(s, sizeof(s), i); else ssh_audit_v6tostr(s, sizeof(s), i); ssh_buffer_append_cstrs(result, " Destination addr:", s, NULL); break; case SSH_AUDIT_SOURCE_ADDRESS_STR: i = va_arg(ap, unsigned char *); if (i == NULL) break; ssh_buffer_append_cstrs(result, " Source addr:", i, NULL); break; case SSH_AUDIT_DESTINATION_ADDRESS_STR: i = va_arg(ap, unsigned char *); if (i == NULL) break; ssh_buffer_append_cstrs(result, " Destination addr:", i, NULL); break; case SSH_AUDIT_IPV6_FLOW_ID: i = va_arg(ap, unsigned char *); size = va_arg(ap, size_t); if (i == NULL || size == 0) break; ssh_bin_to_hex_str(s, size, i); ssh_buffer_append_cstrs(result, " IPV6:0x", s, NULL); break; case SSH_AUDIT_SEQUENCE_NUMBER: i = va_arg(ap, unsigned char *); size = va_arg(ap, size_t); if (i == NULL || size == 0) break; ssh_bin_to_hex_str(s, size, i); ssh_buffer_append_cstrs(result, " Sequence NO:0x", s, NULL); break; case SSH_AUDIT_TXT: i = va_arg(ap, unsigned char *); if (i == NULL) break; ssh_buffer_append_cstrs(result, " Description:", i, NULL); break; case SSH_AUDIT_ARGUMENT_END: return result; /* return constructed string */ default: ssh_fatal("ssh_format_audit_string: invalid format code %d (check arguments and SSH_AUDIT_ARGUMENT_END)", (int)format); } } /*NOTREACHED*/ }