예제 #1
0
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;
}
예제 #2
0
/*************************************************************
 * 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;
}
예제 #3
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;
}
예제 #4
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;
}
예제 #5
0
/*! \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;
}
예제 #6
0
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;
}
예제 #7
0
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;
}