bool ssl_connect_wget (int fd, const char *hostname) { SSL *conn; struct scwt_context scwt_ctx; struct openssl_transport_context *ctx; DEBUGP (("Initiating SSL handshake.\n")); assert (ssl_ctx != NULL); conn = SSL_new (ssl_ctx); if (!conn) goto error; #if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) /* If the SSL library was build with support for ServerNameIndication then use it whenever we have a hostname. If not, don't, ever. */ if (! is_valid_ip_address (hostname)) { if (! SSL_set_tlsext_host_name (conn, hostname)) { DEBUGP (("Failed to set TLS server-name indication.")); goto error; } } #endif #ifndef FD_TO_SOCKET # define FD_TO_SOCKET(X) (X) #endif if (!SSL_set_fd (conn, FD_TO_SOCKET (fd))) goto error; SSL_set_connect_state (conn); scwt_ctx.ssl = conn; if (run_with_timeout(opt.read_timeout, ssl_connect_with_timeout_callback, &scwt_ctx)) { DEBUGP (("SSL handshake timed out.\n")); goto timeout; } if (scwt_ctx.result <= 0 || conn->state != SSL_ST_OK) goto error; ctx = xnew0 (struct openssl_transport_context); ctx->conn = conn; /* Register FD with Wget's transport layer, i.e. arrange that our functions are used for reading, writing, and polling. */ fd_register_transport (fd, &openssl_transport, ctx); DEBUGP (("Handshake successful; connected socket %d to SSL handle 0x%0*lx\n", fd, PTR_FORMAT (conn))); return true; error: DEBUGP (("SSL handshake failed.\n")); print_errors (); timeout: if (conn) SSL_free (conn); return false; }
/** Validate an IP host address @param[in] addr_str pointer to string containing address to be validated @param[in] addr pointer to 32-bit memory for returning valid IP address, in network byte-order, if this function returns TRUE @return TRUE if the address in addr_str is valid, FALSE otherwise */ boolean is_valid_ip_host_addr (char *addr_str, uint32_t *addr) { uint32_t d[IP_ADDR_PARTS]; uint32_t temp_addr; int i; /* * Validate input args */ if ((addr == NULL) || (addr_str == NULL)) { return (FALSE); } if (is_valid_ip_address(addr_str)) { i = sscanf(addr_str, "%u.%u.%u.%u", &d[0], &d[1], &d[2], &d[3]); if ( i < 4) { /* Something is really wrong because we have already check */ /* this condition */ return (FALSE); } /* * Cannot be in multicast range (Class D), experimental or bcast * (Class E). These ranges are * multicast: [224.0.0.0 - 239.255.255.255] Class D * experimental: [240.0.0.0 - 254.255.255.255] Class E * broadcast: [255.0.0.0 - 255.255.255.255] Class E */ if (d[0] > 223) { return (FALSE); } temp_addr = d[0] << 24 | d[1] << 16 | d[2] << 8 | d[3]; if (temp_addr == INADDR_NONE) { return (FALSE); } if (temp_addr == INADDR_ANY) { return (FALSE); } /* * Return IP Address, in network byte-order */ *addr = htonl(temp_addr); return (TRUE); } else { return (FALSE); } }
/* Configuring IPv6 default gateway on management interface. * On success, returns CMD_SUCCESS. On failure, returns CMD_OVSDB_FAILURE. */ static int mgmt_intf_set_default_gw_ipv6(bool set, const char *gw_v6) { const struct ovsrec_system *row = NULL; struct smap smap = SMAP_INITIALIZER(&smap); const char *cfg_gw = NULL; struct ovsdb_idl_txn* status_txn = NULL; enum ovsdb_idl_txn_status status; if (!is_valid_ip_address(gw_v6)) { vty_out(vty, " %s %s", OVSDB_INVALID_IPV4_IPV6_ERROR,VTY_NEWLINE); return CMD_SUCCESS; } status_txn = cli_do_config_start(); if (NULL == status_txn) { VLOG_ERR(OVSDB_TXN_CREATE_ERROR); cli_do_config_abort(status_txn); return CMD_OVSDB_FAILURE; } row = ovsrec_system_first(idl); if (!row) { VLOG_ERR(OVSDB_ROW_FETCH_ERROR); cli_do_config_abort(status_txn); return CMD_OVSDB_FAILURE; } if (!is_mode_static(row)) { vty_out(vty, " %s %s", OVSDB_MODE_ERROR, VTY_NEWLINE); cli_do_config_abort(status_txn); return CMD_SUCCESS; } smap_clone(&smap, &row->mgmt_intf); if(!smap_get(&smap, SYSTEM_MGMT_INTF_MAP_IPV6)) { vty_out(vty, " %s %s", OVSDB_NO_IP_ERROR, VTY_NEWLINE); cli_do_config_abort(status_txn); smap_destroy(&smap); return CMD_SUCCESS; } if (set) { smap_replace(&smap, SYSTEM_MGMT_INTF_MAP_DEFAULT_GATEWAY_V6, gw_v6); } else { cfg_gw = smap_get(&smap, SYSTEM_MGMT_INTF_MAP_DEFAULT_GATEWAY_V6); if (!cfg_gw || strcmp(gw_v6, cfg_gw) != 0) { vty_out(vty, " %s %s", OVSDB_INVALID_VALUE_ERROR, VTY_NEWLINE); cli_do_config_abort(status_txn); smap_destroy(&smap); return CMD_SUCCESS; } smap_replace(&smap, SYSTEM_MGMT_INTF_MAP_DEFAULT_GATEWAY_V6, MGMT_INTF_DEFAULT_IPV6); } ovsrec_system_set_mgmt_intf(row, &smap); smap_destroy(&smap); status = cli_do_config_finish(status_txn); if (TXN_SUCCESS == status || TXN_UNCHANGED == status) { return CMD_SUCCESS; } else { VLOG_ERR(OVSDB_TXN_COMMIT_ERROR); return CMD_OVSDB_FAILURE; } }
/* Configuring static ip on management interface. * On success, returns CMD_SUCCESS. On failure, returns CMD_OVSDB_FAILURE. */ static int mgmt_intf_set_static(bool set, const char *ip, enum ip_type type) { const struct ovsrec_system *row = NULL; struct smap smap = SMAP_INITIALIZER(&smap); struct ovsdb_idl_txn* status_txn = NULL; enum ovsdb_idl_txn_status status; const char *subnet = NULL; const char *ip_addr = NULL; unsigned short subnet_in = 0; char buf[MAX_IPV4_OR_IPV6_SUBNET_CIDR_STR_LEN]; if (!is_valid_ip_address(ip)) { vty_out(vty, " %s %s", OVSDB_INVALID_IPV4_IPV6_ERROR, VTY_NEWLINE); return CMD_SUCCESS; } memset(buf, 0, MAX_IPV4_OR_IPV6_SUBNET_CIDR_STR_LEN); strncpy(buf, ip, MAX_IPV4_OR_IPV6_SUBNET_CIDR_STR_LEN); ip_addr = strtok(buf, "/"); subnet = strtok(NULL, "\0"); subnet_in = atoi(subnet); if (IPV4 == type) { if (IS_INVALID_IPV4_SUBNET(subnet_in)) { vty_out(vty, " %s %s", OVSDB_INVALID_SUBNET_ERROR, VTY_NEWLINE); return CMD_SUCCESS; } }else if (IPV6 == type) { if (IS_INVALID_IPV6_SUBNET(subnet_in)) { vty_out(vty, " %s %s", OVSDB_INVALID_SUBNET_ERROR, VTY_NEWLINE); return CMD_SUCCESS; } } status_txn = cli_do_config_start(); if (NULL == status_txn) { VLOG_ERR(OVSDB_TXN_CREATE_ERROR); cli_do_config_abort(status_txn); return CMD_OVSDB_FAILURE; } row = ovsrec_system_first(idl); if (!row) { VLOG_ERR(OVSDB_ROW_FETCH_ERROR); cli_do_config_abort(status_txn); return CMD_OVSDB_FAILURE; } smap_clone(&smap, &row->mgmt_intf); if (set) smap_replace(&smap, SYSTEM_MGMT_INTF_MAP_MODE, SYSTEM_MGMT_INTF_MAP_MODE_STATIC); if (IPV4 == type) { if (set) { smap_replace(&smap, SYSTEM_MGMT_INTF_MAP_IP, ip_addr); smap_replace(&smap, SYSTEM_MGMT_INTF_MAP_SUBNET_MASK, subnet); } else { if (mgmt_intf_remove_static_ipv4_address(&smap, ip_addr, subnet) != CMD_SUCCESS) { cli_do_config_abort(status_txn); smap_destroy(&smap); return CMD_SUCCESS; } } }else if (IPV6 == type) { if (set) smap_replace(&smap, SYSTEM_MGMT_INTF_MAP_IPV6, ip); else { if (mgmt_intf_remove_static_ipv6_address(&smap, ip) != CMD_SUCCESS) { cli_do_config_abort(status_txn); smap_destroy(&smap); return CMD_SUCCESS; } } } ovsrec_system_set_mgmt_intf(row, &smap); smap_destroy(&smap); status = cli_do_config_finish(status_txn); if (TXN_SUCCESS == status || TXN_UNCHANGED == status) { return CMD_SUCCESS; } else { VLOG_ERR(OVSDB_TXN_COMMIT_ERROR); return CMD_OVSDB_FAILURE; } }
/** * Called when a command is being sent from the plugin. */ void pipeCommand(PipeCommand command, const char *url, const char *hostname, const char *ip) { switch (command) { case PC_GetVersion: { char *versionString = bankid_getVersion(); pipe_sendString(stdout, versionString); free(versionString); pipe_flush(stdout); platform_leaveMainloop(); break; } case PC_Authenticate: case PC_Sign: { char *challenge = pipe_readString(stdin); int32_t serverTime = pipe_readInt(stdin); free(pipe_readOptionalString(stdin)); // Just ignore the policies list for now char *subjectFilter = pipe_readOptionalString(stdin); char *messageEncoding = NULL, *message = NULL, *invisibleMessage = NULL; if (command == PC_Sign) { messageEncoding = pipe_readString(stdin); message = pipe_readString(stdin); invisibleMessage = pipe_readOptionalString(stdin); } // Validate input BankIDError error = BIDERR_OK; if (!is_https_url(url)) { error = BIDERR_NotSSL; } else if (!is_canonical_base64(challenge) || !is_valid_hostname(hostname) || !is_valid_ip_address(ip) || (command == PC_Sign && ( !is_canonical_base64(message) || (invisibleMessage && !is_canonical_base64(invisibleMessage)) ))) { error = BIDERR_InternalError; } if (error != BIDERR_OK) { pipe_sendInt(stdout, error); pipe_sendString(stdout, ""); pipe_flush(stdout); platform_leaveMainloop(); return; } if (subjectFilter && !is_canonical_base64(subjectFilter)) { // The subject filter is invalid. Ignore it free(subjectFilter); subjectFilter = NULL; } Token *token; char *password = NULL; long password_maxsize = 0; char *signature = NULL; char *decodedSubjectFilter = NULL; error = BIDERR_UserCancel; // Allocate a secure page for the password password = secmem_get_page(&password_maxsize); if (!password || !password_maxsize) { pipe_sendInt(stdout, BIDERR_InternalError); pipe_sendString(stdout, ""); pipe_flush(stdout); platform_leaveMainloop(); return; } if (subjectFilter) { decodedSubjectFilter = base64_decode(subjectFilter); free(subjectFilter); } // Pass all parameters to the user interface platform_startSign(url, hostname, ip, browserWindowId); BackendNotifier *notifier = backend_createNotifier( decodedSubjectFilter, (command == PC_Sign ? KeyUsage_Signing : KeyUsage_Authentication), notifyCallback); platform_setNotifier(notifier); platform_addKeyDirectories(); backend_scanTokens(notifier); free(decodedSubjectFilter); if (command == PC_Sign) { if (!message) abort(); char *decodedMessage = base64_decode(message); platform_setMessage(decodedMessage); free(decodedMessage); } while (platform_sign(&token, password, password_maxsize)) { // Set the password (not used by all backends) token_usePassword(token, password); // Try to authenticate/sign if (command == PC_Authenticate) { error = bankid_authenticate(token, challenge, serverTime, hostname, ip, &signature); } else { error = bankid_sign(token, challenge, serverTime, hostname, ip, messageEncoding, message, invisibleMessage, &signature); } guaranteed_memset(password, 0, password_maxsize); if (error == BIDERR_OK) break; // An error occurred const TokenError tokenError = token_getLastError(token); platform_showError(tokenError); if (tokenError == TokenError_BadPassword || tokenError == TokenError_BadPin) { platform_focusPassword(); // also removes focus from the Sign button } error = BIDERR_UserCancel; } secmem_free_page(password); platform_endSign(); backend_freeNotifier(notifier); free(messageEncoding); free(message); free(invisibleMessage); free(challenge); pipe_sendInt(stdout, error); pipe_sendString(stdout, (signature ? signature : "")); pipe_flush(stdout); free(signature); platform_leaveMainloop(); break; } case PC_CreateRequest: { char *request = NULL; BankIDError error = BIDERR_InternalError; long password_maxsize = 0; char *name = NULL; char *password = NULL; // Read input RegutilInfo input; memset(&input, 0, sizeof(input)); input.minPasswordLength = pipe_readInt(stdin); input.minPasswordNonDigits = pipe_readInt(stdin); input.minPasswordDigits = pipe_readInt(stdin); while (pipe_readInt(stdin) == PLS_MoreData) { // PKCS10 RegutilPKCS10 *pkcs10 = malloc(sizeof(RegutilPKCS10)); pkcs10->keyUsage = pipe_readInt(stdin); pkcs10->keySize = pipe_readInt(stdin); pkcs10->subjectDN = pipe_readString(stdin); pkcs10->includeFullDN = pipe_readInt(stdin); pkcs10->next = input.pkcs10; input.pkcs10 = pkcs10; } // CMC input.cmc.oneTimePassword = pipe_readString(stdin); input.cmc.rfc2729cmcoid = pipe_readString(stdin); // Check for broken pipe if (feof(stdin)) goto createReq_end; // Check input if (!input.pkcs10) goto createReq_end; // Get name to display name = bankid_getRequestDisplayName(&input); if (!name) goto createReq_end; // Allocate a secure page for the password password = secmem_get_page(&password_maxsize); if (!password || !password_maxsize) goto createReq_end; platform_startChoosePassword(name, browserWindowId); platform_setPasswordPolicy(input.minPasswordLength, input.minPasswordNonDigits, input.minPasswordDigits); for (;;) { error = RUERR_UserCancel; // Ask for a password if (!platform_choosePassword(password, password_maxsize)) break; // Try to authenticate/sign // Generate key pair and construct the request TokenError tokenError; error = bankid_createRequest(&input, hostname, password, &request, &tokenError); guaranteed_memset(password, 0, password_maxsize); if (error == BIDERR_OK) break; platform_showError(tokenError); } platform_endChoosePassword(); // Send result createReq_end: secmem_free_page(password); pipe_sendInt(stdout, error); if (!request) pipe_sendString(stdout, ""); else { pipe_sendString(stdout, request); free(request); } pipe_flush(stdout); platform_leaveMainloop(); break; } case PC_StoreCertificates: { char *certs = pipe_readString(stdin); TokenError tokenError; BankIDError error = bankid_storeCertificates(certs, hostname, &tokenError); if (error != BIDERR_OK) { if (prefs_debug_dump) { certutil_dumpCertsP7(certs); } platform_showError(tokenError); } pipe_sendInt(stdout, error); pipe_flush(stdout); platform_leaveMainloop(); break; } default: { fprintf(stderr, BINNAME ": invalid command from pipe\n"); platform_leaveMainloop(); break; } } }