int handle_logout_command(struct thread_data_t * datum, char * args) { int i, len; char buffer[MAX_COMMAND_LENGTH]; /* Logout command takes no arguments */ #ifndef NDEBUG if (*args != '\0') { fprintf(stderr, "[thread %lu] WARNING: ignoring '%s' (argument residue)\n", datum->id, args); } #endif /* Prepare a reply dependent on our state */ memset(buffer, '\0', MAX_COMMAND_LENGTH); if (datum->credentials.userlength) { snprintf(buffer, MAX_COMMAND_LENGTH, "Goodbye, %s!", datum->credentials.username); } else { snprintf(buffer, MAX_COMMAND_LENGTH, "LOGOUT ERROR"); } salt_and_pepper(buffer, NULL, &datum->buffet); encrypt_message(&datum->buffet, datum->credentials.key); /* Clear the credential bits from the key */ if (datum->credentials.userlength) { len = datum->credentials.userlength; for (i = 0; i < AUTH_KEY_LENGTH; ++i) { datum->credentials.key[i] ^= datum->credentials.username[i % len]; } memset(&datum->credentials.username, '\0', MAX_COMMAND_LENGTH); datum->credentials.userlength = 0; } send_message(&datum->buffet, datum->sock); /* Handle verification (should fail) */ recv_message(&datum->buffet, datum->sock); decrypt_message(&datum->buffet, datum->credentials.key); for (i = 0; i < MAX_COMMAND_LENGTH; ++i) { datum->buffet.pbuffer[i] = datum->buffet.tbuffer[MAX_COMMAND_LENGTH - 1 - i]; } encrypt_message(&datum->buffet, datum->credentials.key); send_message(&datum->buffet, datum->sock); return BANKING_SUCCESS; }
int handle_balance_command(struct thread_data_t * datum, char * args) { long int balance; char buffer[MAX_COMMAND_LENGTH]; /* Balance command takes no arguments */ #ifndef NDEBUG if (*args != '\0') { fprintf(stderr, "[thread %lu] WARNING: ignoring '%s' (argument residue)\n", datum->id, args); } #endif /* Formulate a response */ memset(buffer, '\0', MAX_COMMAND_LENGTH); /* If we have a username, try to do a lookup */ if (datum->credentials.userlength && do_lookup(session_data.db_conn, NULL, datum->credentials.username, datum->credentials.userlength, &balance) == BANKING_SUCCESS) { snprintf(buffer, MAX_COMMAND_LENGTH, "%s, your balance is $%li.", datum->credentials.username, balance); } else { snprintf(buffer, MAX_COMMAND_LENGTH, "BALANCE ERROR"); } /* Send the results */ salt_and_pepper(buffer, NULL, &datum->buffet); encrypt_message(&datum->buffet, datum->credentials.key); send_message(&datum->buffet, datum->sock); return BANKING_SUCCESS; }
int encrypt(unsigned char* ciphertext, size_t* ciphertext_length, unsigned char* key) { unsigned char message[] = MESSAGE; printf("Message (%lu Bytes):\n%s\n\n", sizeof(message), message); //create random nonce unsigned char nonce[crypto_secretbox_NONCEBYTES]; randombytes_buf(nonce, crypto_secretbox_NONCEBYTES); //print nonce printf("Nonce (%i Bytes):\n", crypto_secretbox_NONCEBYTES); print_hex(nonce, crypto_secretbox_NONCEBYTES, 30); putchar('\n'); const unsigned char header[] = HEADER; printf("Header (%lu Bytes):\n%s\n\n", sizeof(header), header); int status = encrypt_message( ciphertext, ciphertext_length, message, sizeof(message), header, sizeof(header), nonce, key); sodium_memzero(message, sizeof(message)); return status; }
static PyObject* authGSSWinRMEncryptMessage(PyObject* self, PyObject* args) { char *input = NULL; char *header = NULL; int header_len = 0; char *enc_output = NULL; int enc_output_len = 0; PyObject *pystate = NULL; gss_client_state *state = NULL; int result = 0; PyObject *pyresult = NULL; // NB: use et so we get a copy of the string (since gss_wrap_iov mutates it), and so we're certain it's always // a UTF8 byte string if (! PyArg_ParseTuple(args, "Oet", &pystate, "UTF-8", &input)) { pyresult = NULL; goto end; } if (!PyCheck(pystate)) { PyErr_SetString(PyExc_TypeError, "Expected a context object"); pyresult = NULL; goto end; } state = PyGet(pystate, gss_client_state); if (state == NULL) { pyresult = NULL; goto end; } result = encrypt_message(state, input, &header, &header_len, &enc_output, &enc_output_len); if (result == AUTH_GSS_ERROR) { pyresult = NULL; goto end; } #if PY_MAJOR_VERSION >= 3 pyresult = Py_BuildValue("y# y#", enc_output, enc_output_len, header, header_len); #else pyresult = Py_BuildValue("s# s#", enc_output, enc_output_len, header, header_len); #endif end: if (input) { PyMem_Free(input); } if (header) { free(header); } if (enc_output) { free(enc_output); } return pyresult; }
int handle_transfer_command(struct thread_data_t * datum, char * args) { long amount, balance; char * user, buffer[MAX_COMMAND_LENGTH]; #ifndef NDEBUG if (*args == '\0') { fprintf(stderr, "[thread %lu] WARNING: [%s] arguments empty\n", datum->id, "transfer"); } else { fprintf(stderr, "[thread %lu] INFO: [%s] '%s' (arguments)\n", datum->id, "transfer", args); } #endif amount = strtol(args, &args, 10); user = ++args; if (amount <= 0 || amount > MAX_TRANSACTION) { snprintf(buffer, MAX_COMMAND_LENGTH, "Invalid transfer amount."); } else if (datum->credentials.userlength && do_lookup(session_data.db_conn, NULL, datum->credentials.username, datum->credentials.userlength, &balance) == BANKING_SUCCESS) { if (balance < amount) { snprintf(buffer, MAX_COMMAND_LENGTH, "Insufficient funds."); } else if (do_update(session_data.db_conn, NULL, datum->credentials.username, datum->credentials.userlength, balance - amount) || do_lookup(session_data.db_conn, NULL, user, strnlen(user, MAX_COMMAND_LENGTH), &balance) || do_update(session_data.db_conn, NULL, user, strnlen(user, MAX_COMMAND_LENGTH), balance + amount)) { /* TODO atomic operation? */ snprintf(buffer, MAX_COMMAND_LENGTH, "Cannot complete transfer."); } else { snprintf(buffer, MAX_COMMAND_LENGTH, "Transfered $%li to %s", amount, user); } } else { snprintf(buffer, MAX_COMMAND_LENGTH, "TRANSFER ERROR"); } salt_and_pepper(buffer, NULL, &datum->buffet); encrypt_message(&datum->buffet, datum->credentials.key); send_message(&datum->buffet, datum->sock); return BANKING_SUCCESS; }
void out_thread(master_post_office* o) try { REQUIRE(o); std::string last_address; while(!o->_done) try { //get message from queue message m; if(!o->_out.pop(m, true)) continue; REQUIRE_GREATER_EQUAL(m.meta.from.size(), 1); REQUIRE_GREATER_EQUAL(m.meta.to.size(), 1); const std::string outside_queue_address = m.meta.to.front(); last_address = outside_queue_address; //encode, compress, and encrypt message auto data = u::encode(m); data = u::compress(data); encrypt_message( data, m, outside_queue_address, *o->_encrypted_channels); //send message over wire o->_connections.send(outside_queue_address, data, m.meta.robust); if(o->_outside_stats.on) o->_outside_stats.out_pop_count++; } catch(std::exception& e) { LOG << "error sending message to " << last_address << ": " << e.what() << std::endl; } catch(...) { LOG << "error sending message to " << last_address << ": unknown error." << std::endl; } u::sleep_thread(QUIT_SLEEP); } catch(...) { LOG << "exit: master_post::out_thread" << std::endl; }
int handle_withdraw_command(struct thread_data_t * datum, char * args) { long balance, amount; char buffer[MAX_COMMAND_LENGTH]; #ifndef NDEBUG if (*args == '\0') { fprintf(stderr, "[thread %lu] WARNING: [%s] arguments empty\n", datum->id, "withdraw"); } else { fprintf(stderr, "[thread %lu] INFO: [%s] '%s' (arguments)\n", datum->id, "withdraw", args); } #endif amount = strtol(args, &args, 10); if (amount <= 0 || amount > MAX_TRANSACTION) { snprintf(buffer, MAX_COMMAND_LENGTH, "Invalid withdrawal amount."); } else if (datum->credentials.userlength && do_lookup(session_data.db_conn, NULL, datum->credentials.username, datum->credentials.userlength, &balance) == BANKING_SUCCESS) { if (balance < amount) { snprintf(buffer, MAX_COMMAND_LENGTH, "Insufficient funds."); } else if (do_update(session_data.db_conn, NULL, datum->credentials.username, datum->credentials.userlength, balance - amount)) { snprintf(buffer, MAX_COMMAND_LENGTH, "Cannot complete withdrawal."); } else { snprintf(buffer, MAX_COMMAND_LENGTH, "Withdrew $%li", amount); } } else { snprintf(buffer, MAX_COMMAND_LENGTH, "WITHDRAW ERROR"); } salt_and_pepper(buffer, NULL, &datum->buffet); encrypt_message(&datum->buffet, datum->credentials.key); send_message(&datum->buffet, datum->sock); return BANKING_SUCCESS; }
void * handle_client(void * arg) { struct thread_data_t * datum = (struct thread_data_t *)(arg); /* Fetch the ID from the argument */ #ifndef NDEBUG fprintf(stderr, "[thread %lu] INFO: worker started\n", datum->id); #endif /* Worker thread signal handling is unique */ sigaction(SIGUSR1, datum->signal_action, NULL); sigaction(SIGUSR2, datum->signal_action, NULL); /* As long as possible, grab up whatever connection is available */ while (!session_data.caught_signal && !datum->caught_signal) { /* Ensure only one worker accepts the next client */ gcry_pthread_mutex_lock((void **)(&session_data.accept_mutex)); datum->sock = accept(session_data.sock, (struct sockaddr *)(&datum->remote_addr), &datum->remote_addr_len); gcry_pthread_mutex_unlock((void **)(&session_data.accept_mutex)); if (datum->sock >= 0) { #ifndef NDEBUG fprintf(stderr, "[thread %lu] INFO: worker connected to client\n", datum->id); #endif /* Receive a "hello" message from the client */ recv_message(&datum->buffet, datum->sock); /* Decrypt it with the default key */ decrypt_message(&datum->buffet, keystore.key); /* Verify it is an authentication request */ if (strncmp(datum->buffet.tbuffer, AUTH_CHECK_MSG, sizeof(AUTH_CHECK_MSG))) { /* Respond with nonce (misdirection) */ gcry_create_nonce(datum->buffet.pbuffer, MAX_COMMAND_LENGTH); encrypt_message(&datum->buffet, keystore.key); send_message(&datum->buffet, datum->sock); } else { /* Request a session key */ gcry_pthread_mutex_lock((void **)(&session_data.keystore_mutex)); #ifndef NDEBUG print_keystore(stderr, "before request"); #endif request_key(&datum->credentials.key); #ifndef NDEBUG print_keystore(stderr, "after request"); #endif gcry_pthread_mutex_unlock((void **)(&session_data.keystore_mutex)); /* Encrypted it using the default key */ salt_and_pepper((char *)(datum->credentials.key), NULL, &datum->buffet); encrypt_message(&datum->buffet, keystore.key); send_message(&datum->buffet, datum->sock); clear_buffet(&datum->buffet); /* Repeatedly poll for message streams */ while (handle_stream(datum) == BANKING_SUCCESS); /* Revoke the session key */ gcry_pthread_mutex_lock((void **)(&session_data.keystore_mutex)); #ifndef NDEBUG print_keystore(stderr, "before revoke"); #endif revoke_key(&datum->credentials.key); #ifndef NDEBUG print_keystore(stderr, "after revoke"); #endif gcry_pthread_mutex_unlock((void **)(&session_data.keystore_mutex)); } /* Cleanup (disconnect) */ #ifndef NDEBUG fprintf(stderr, "[thread %lu] INFO: worker disconnected from client\n", datum->id); #endif clear_buffet(&datum->buffet); destroy_socket(datum->sock); datum->sock = BANKING_FAILURE; } else { fprintf(stderr, "[thread %lu] ERROR: worker unable to connect\n", datum->id); } } /* Teardown */ handle_interruption(0); return NULL; }
/*! \brief Handle a message stream from a client */ int handle_stream(struct thread_data_t * datum) { int i; handle_t hdl; char msg[MAX_COMMAND_LENGTH], * args; /* The initial message is always an authentication request */ recv_message(&datum->buffet, datum->sock); decrypt_message(&datum->buffet, datum->credentials.key); if (strncmp(datum->buffet.tbuffer, AUTH_CHECK_MSG, sizeof(AUTH_CHECK_MSG))) { #ifndef NDEBUG fprintf(stderr, "[thread %lu] INFO: malformed authentication message\n", datum->id); #endif /* Respond with a "mumble" (nonce) */ gcry_create_nonce(datum->buffet.pbuffer, MAX_COMMAND_LENGTH); encrypt_message(&datum->buffet, datum->credentials.key); send_message(&datum->buffet, datum->sock); return BANKING_FAILURE; } /* Turn around the buffer and toss it back */ for (i = 0; i < MAX_COMMAND_LENGTH; ++i) { datum->buffet.pbuffer[i] = datum->buffet.tbuffer[MAX_COMMAND_LENGTH - 1 - i]; } encrypt_message(&datum->buffet, datum->credentials.key); send_message(&datum->buffet, datum->sock); clear_buffet(&datum->buffet); #ifndef NDEBUG fprintf(stderr, "[thread %lu] INFO: authentication successful\n", datum->id); #endif /* Read the actual command */ recv_message(&datum->buffet, datum->sock); decrypt_message(&datum->buffet, datum->credentials.key); /* Copy the command into a buffer so more can be received */ strncpy(msg, datum->buffet.tbuffer, MAX_COMMAND_LENGTH); #ifndef NDEBUG /* Local echo for all received messages */ fprintf(stderr, "[thread %lu] INFO: worker received message:\n", datum->id); hexdump(stderr, (unsigned char *)(msg), MAX_COMMAND_LENGTH); #endif /* Disconnect from any client that issues malformed commands */ if (fetch_handle(msg, &hdl, &args)) { /* Respond with a "mumble" (nonce) */ gcry_create_nonce(datum->buffet.pbuffer, MAX_COMMAND_LENGTH); encrypt_message(&datum->buffet, datum->credentials.key); send_message(&datum->buffet, datum->sock); clear_buffet(&datum->buffet); return BANKING_FAILURE; } /* We are signaled by failed handlers */ datum->caught_signal = hdl(datum, args); clear_buffet(&datum->buffet); return BANKING_SUCCESS; }
int handle_login_command(struct thread_data_t * datum, char * args) { size_t i, len; char buffer[MAX_COMMAND_LENGTH]; /* The login argument takes one argument */ #ifndef NDEBUG if (*args == '\0') { fprintf(stderr, "[thread %lu] WARNING: [%s] arguments empty\n", datum->id, "login"); } else { fprintf(stderr, "[thread %lu] INFO: [%s] '%s' (arguments)\n", datum->id, "login", args); } #endif /* TODO verify they're an actual user of the system */ /* Modify the key using bits from the username */ len = strnlen(args, MAX_COMMAND_LENGTH); for (i = 0; i < AUTH_KEY_LENGTH; ++i) { datum->credentials.key[i] ^= args[i % len]; } /* Turn around the message */ for (i = 0; i < MAX_COMMAND_LENGTH; ++i) { datum->buffet.pbuffer[i] = datum->buffet.tbuffer[MAX_COMMAND_LENGTH - 1 - i]; } /* Echo this message with the modified key */ encrypt_message(&datum->buffet, datum->credentials.key); send_message(&datum->buffet, datum->sock); /* Receive the PIN */ recv_message(&datum->buffet, datum->sock); decrypt_message(&datum->buffet, datum->credentials.key); /* Copy the args backward TODO better auth, use pin as salt */ memset(buffer, '\0', MAX_COMMAND_LENGTH); for (i = 0; i < len; ++i) { buffer[i] = args[len - i - 1]; } /* Check the buffer matches the args */ if (strncmp(buffer, datum->buffet.tbuffer, len) || do_lookup(session_data.db_conn, NULL, args, len, NULL)) { snprintf(buffer, MAX_COMMAND_LENGTH, "LOGIN ERROR"); /* Remove the previously added bits */ for (i = 0; i < AUTH_KEY_LENGTH; ++i) { datum->credentials.key[i] ^= args[i % len]; } } else { snprintf(buffer, MAX_COMMAND_LENGTH, "%s, %s!", AUTH_LOGIN_MSG, args); /* We have now authenticated the user */ memset(datum->credentials.username, '\0', MAX_COMMAND_LENGTH); strncpy(datum->credentials.username, args, len); datum->credentials.userlength = len; } salt_and_pepper(buffer, NULL, &datum->buffet); encrypt_message(&datum->buffet, datum->credentials.key); send_message(&datum->buffet, datum->sock); /* Catch authentication check */ recv_message(&datum->buffet, datum->sock); decrypt_message(&datum->buffet, datum->credentials.key); /* Turn around the message */ for (i = 0; i < MAX_COMMAND_LENGTH; ++i) { datum->buffet.pbuffer[i] = datum->buffet.tbuffer[MAX_COMMAND_LENGTH - 1 - i]; } encrypt_message(&datum->buffet, datum->credentials.key); send_message(&datum->buffet, datum->sock); return BANKING_SUCCESS; }