static void pipe_flush_event(void * x) { ChannelPIPE * c = (ChannelPIPE *)x; assert(c->magic == CHANNEL_MAGIC); if (--c->out_flush_cnt == 0) { int congestion_level = c->chan->congestion_level; if (congestion_level > 0) usleep(congestion_level * 2500); pipe_flush(c); pipe_unlock(c->chan); } }
/** * \fn pipe_close * \brief Update reference count and if necessary clean up */ static int pipe_close(struct pipe* pipe) { if (pipe == NULL) return -E_NULL_PTR; if (atomic_dec(&pipe->ref_cnt) == 0) { pipe_flush(pipe); kfree(pipe); } return -E_SUCCESS; }
static void pipe_write_stream(OutputStream * out, int byte) { ChannelPIPE * c = channel2pipe(out2channel(out)); assert(c->magic == CHANNEL_MAGIC); if (c->chan->state == ChannelStateDisconnected) return; if (c->chan->out.cur == c->chan->out.end) pipe_flush(c); if (byte < 0 || byte == ESC) { char esc = 0; *c->chan->out.cur++ = ESC; if (byte == ESC) esc = 0; else if (byte == MARKER_EOM) esc = 1; else if (byte == MARKER_EOS) esc = 2; else assert(0); if (c->chan->state == ChannelStateDisconnected) return; if (c->chan->out.cur == c->chan->out.end) pipe_flush(c); *c->chan->out.cur++ = esc; if (byte == MARKER_EOM && c->out_flush_cnt < 2) { if (c->out_flush_cnt++ == 0) pipe_lock(c->chan); post_event_with_delay(pipe_flush_event, c, 0); } return; } *c->chan->out.cur++ = (char)byte; }
static void pipe_write_block_stream(OutputStream * out, const char * bytes, size_t size) { size_t cnt = 0; ChannelPIPE * c = channel2pipe(out2channel(out)); if (out->supports_zero_copy && size > 32) { /* Send the binary data escape seq */ size_t n = size; if (c->chan->out.cur >= c->chan->out.end - 8) pipe_flush(c); *c->chan->out.cur++ = ESC; *c->chan->out.cur++ = 3; for (;;) { if (n <= 0x7fu) { *c->chan->out.cur++ = (char)n; break; } *c->chan->out.cur++ = (n & 0x7fu) | 0x80u; n = n >> 7; } /* We need to flush the buffer then send our data */ pipe_flush(c); create_write_request(c, bytes, size); return; }
/** * 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; } } }
int slip_set_addrs() { char buf[128]; char type[30]; char addr[30]; int res; if (waiting_for_bootp && (!have_local || !have_remote)) { int i; char *buf, *tail; buf = tail = bootp_pipe.buf; i = pipe_read(&bootp_pipe); if (i <= 0) return 0; while (i--) { if (*tail == '\n') { *tail = 0; /* Got a line, deal with it */ if (sscanf(buf,"%[^=]=%s\n",type,addr) == 2) { if (strcmp(type,"SERVER")==0) { have_remote = 1; remote_ip = strdup(addr); } else if (strcmp(type,"IPADDR")==0) { have_local = 1; local_ip = strdup(addr); } } buf = tail+1; } tail++; } pipe_flush(&bootp_pipe,buf-bootp_pipe.buf); } if (waiting_for_bootp && (!have_local || !have_remote)) return 0; if (waiting_for_bootp) { pclose(bootpfp); syslog(LOG_INFO,"New addresses: local %s, remote %s.", local_ip,remote_ip); waiting_for_bootp = 0; } if (route_wait) { /* set the initial rx counter once the link is up */ if (rx_count == -1) rx_count = slip_rx_count(); /* check if we got the routing packet yet */ if (slip_rx_count() == rx_count) return 0; } /* redo the interface marking and the routing since BOOTP will change it */ if (netmask) { sprintf(buf,"%s sl%d %s pointopoint %s netmask %s mtu %d up", PATH_IFCONFIG,link_iface,local_ip,remote_ip,netmask,mtu); } else { sprintf(buf,"%s sl%d %s pointopoint %s mtu %d up", PATH_IFCONFIG,link_iface,local_ip,remote_ip,mtu); } res = system(buf); report_system_result(res,buf); /* Set the routing for the new slip interface */ set_ptp("sl",link_iface,remote_ip,metric); if (dynamic_addrs || force_dynamic) { local_addr = inet_addr(local_ip); /* have to reset the proxy if we won't be rerouting... */ if (!do_reroute) { proxy_config(local_ip,remote_ip); set_ptp("sl",proxy_iface,remote_ip,metric+1); add_routes("sl",proxy_iface,local_ip,remote_ip,drmetric+1); } } if (do_reroute) add_routes("sl",link_iface,local_ip,remote_ip,drmetric); return 1; }