static BankIDError waitReply(PipeInfo *pipeinfo) { pipe_finishCommand(pipeinfo->out); pipe_waitData(pipeinfo->in); // Return error code return pipe_readInt(pipeinfo->in); }
void pipe_readData(FILE *in, char **data, int *length) { *length = pipe_readInt(in); if (*length <= 0) { *length = 0; *data = NULL; return; } *data = malloc(*length); if ((*data == NULL) || (fread(*data, *length, 1, in) != 1)) { pipeError(); free(*data); *length = 0; } }
char *pipe_readString(FILE *in) { int length = pipe_readInt(in); if (length <= 0) return strdup(""); char *data = malloc(length +1); if (!data) { pipeError(); return strdup(""); } data[length] = '\0'; if (fread(data, length, 1, in) == 1) { return data; } else { pipeError(); free(data); return strdup(""); } }
/** * 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; } } }
PipeCommand pipe_readCommand(FILE *in) { return pipe_readInt(in); }