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; }
/************************************************************* * Reads encrypted text and creates encoded and * * plain text files * *************************************************************/ int main(int argc, char* argv[]) { FILE *f_plane_ptr, *f_encoded_ptr, *f_crypted_ptr; /* exit program and print error if encrypted text file could not be opened to read */ /* exit program and print error if encoded text file could not be opened to write */ decrypt_message(f_crypted_ptr, f_encoded_ptr); /* close encrypted and encoded files */ /* exit program and print error if plain text file could not be opened to write */ /* exit program and print error if encoded text file could not be opened to read */ decode_message(f_encoded_ptr, f_plane_ptr); /* close encoded and plain files */ return 0; }
// do process input requests, return 0 is done, 1 is call again to complete int DoProcessReply(SSL& ssl) { // wait for input if blocking if (!ssl.useSocket().wait()) { ssl.SetError(receive_error); return 0; } uint ready = ssl.getSocket().get_ready(); if (!ready) ready= 64; // add buffered data if its there input_buffer* buffered = ssl.useBuffers().TakeRawInput(); uint buffSz = buffered ? buffered->get_size() : 0; input_buffer buffer(buffSz + ready); if (buffSz) { buffer.assign(buffered->get_buffer(), buffSz); ysDelete(buffered); buffered = 0; } // add new data uint read = ssl.useSocket().receive(buffer.get_buffer() + buffSz, ready); if (read == static_cast<uint>(-1)) { ssl.SetError(receive_error); return 0; } buffer.add_size(read); uint offset = 0; const MessageFactory& mf = ssl.getFactory().getMessage(); // old style sslv2 client hello? if (ssl.getSecurity().get_parms().entity_ == server_end && ssl.getStates().getServer() == clientNull) if (buffer.peek() != handshake) { ProcessOldClientHello(buffer, ssl); if (ssl.GetError()) return 0; } while(!buffer.eof()) { // each record RecordLayerHeader hdr; bool needHdr = false; if (static_cast<uint>(RECORD_HEADER) > buffer.get_remaining()) needHdr = true; else { buffer >> hdr; ssl.verifyState(hdr); } if (ssl.GetError()) return 0; // make sure we have enough input in buffer to process this record if (needHdr || hdr.length_ > buffer.get_remaining()) { // put header in front for next time processing uint extra = needHdr ? 0 : RECORD_HEADER; uint sz = buffer.get_remaining() + extra; ssl.useBuffers().SetRawInput(NEW_YS input_buffer(sz, buffer.get_buffer() + buffer.get_current() - extra, sz)); return 1; } while (buffer.get_current() < hdr.length_ + RECORD_HEADER + offset) { // each message in record, can be more than 1 if not encrypted if (ssl.GetError()) return 0; if (ssl.getSecurity().get_parms().pending_ == false) { // cipher on // sanity check for malicious/corrupted/illegal input if (buffer.get_remaining() < hdr.length_) { ssl.SetError(bad_input); return 0; } decrypt_message(ssl, buffer, hdr.length_); if (ssl.GetError()) return 0; } mySTL::auto_ptr<Message> msg(mf.CreateObject(hdr.type_)); if (!msg.get()) { ssl.SetError(factory_error); return 0; } buffer >> *msg; msg->Process(buffer, ssl); if (ssl.GetError()) return 0; } offset += hdr.length_ + RECORD_HEADER; } return 0; }
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; }
static PyObject* authGSSWinRMDecryptMessage(PyObject* self, PyObject* args) { char *header = NULL; int header_len = 0; char *enc_data = NULL; int enc_data_len = 0; PyObject *pystate = NULL; PyObject *pyheader = NULL; PyObject *pyenc_data = NULL; gss_client_state *state = NULL; char *dec_output = NULL; int dec_output_len = 0; int result = 0; PyObject *pyresult = 0; // NB: since the sig/data strings are arbitrary binary and don't conform to // a valid encoding, none of the normal string marshaling types will work. We'll // have to extract the data later. if (! PyArg_ParseTuple(args, "OOO", &pystate, &pyenc_data, &pyheader)) { 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; } // request the length and copy the header and encrypted input data from the Python strings header_len = (int) PyBytes_Size(pyheader); header = malloc(header_len); memcpy(header, PyBytes_AsString(pyheader), header_len); enc_data_len = (int) PyBytes_Size(pyenc_data); enc_data = malloc(enc_data_len); memcpy(enc_data, PyBytes_AsString(pyenc_data), enc_data_len); result = decrypt_message(state, header, header_len, enc_data, enc_data_len, &dec_output, &dec_output_len); if (result == AUTH_GSS_ERROR) { pyresult = NULL; goto end; } #if PY_MAJOR_VERSION >= 3 pyresult = Py_BuildValue("y#", dec_output, dec_output_len); #else pyresult = Py_BuildValue("s#", dec_output, dec_output_len); #endif end: if (header) { free(header); } if (enc_data) { free(enc_data); } if (dec_output) { free(dec_output); } return pyresult; }