Пример #1
0
void SFTP::process(void)
{
  const u_int msg_len = buffer_get_int (&iqueue);
	const u_int type = buffer_get_char(&iqueue);
	switch (type) {
	case SSH2_FXP_INIT:
		process_init();
		break;
	case SSH2_FXP_OPEN:
		process_open();
		break;
	case SSH2_FXP_CLOSE:
		process_close();
		break;
	case SSH2_FXP_READ:
		process_read();
		break;
	case SSH2_FXP_WRITE:
		process_write();
		break;
	case SSH2_FXP_LSTAT:
		process_lstat();
		break;
	case SSH2_FXP_FSTAT:
		process_fstat();
		break;
	case SSH2_FXP_SETSTAT:
		process_setstat();
		break;
	case SSH2_FXP_FSETSTAT:
		process_fsetstat();
		break;
	case SSH2_FXP_OPENDIR:
		process_opendir();
		break;
	case SSH2_FXP_READDIR:
		process_readdir();
		break;
	case SSH2_FXP_REMOVE:
		process_remove();
		break;
	case SSH2_FXP_MKDIR:
		process_mkdir();
		break;
	case SSH2_FXP_RMDIR:
		process_rmdir();
		break;
	case SSH2_FXP_REALPATH:
		process_realpath();
		break;
	case SSH2_FXP_STAT:
		process_stat();
		break;
	case SSH2_FXP_RENAME:
		process_rename();
		break;
	case SSH2_FXP_READLINK:
		process_readlink();
		break;
	case SSH2_FXP_SYMLINK:
		process_symlink();
		break;
	case SSH2_FXP_EXTENDED:
		process_extended();
		break;
	default:
		error("Unknown message %d", type);
		break;
	}

  /* discard the remaining bytes from the current packet */
	
  if (msg_len < buffer_len(&iqueue)) {
		error("iqueue grew unexpectedly");
		sftp_server_cleanup_exit(255);
	}
	u_int consumed = msg_len - buffer_len(&iqueue);
	if (msg_len < consumed) {
		error("msg_len %d < consumed %d", msg_len, consumed);
		sftp_server_cleanup_exit(255);
	}
	if (msg_len > consumed)
		buffer_consume(&iqueue, msg_len - consumed);
}
Пример #2
0
int
main(int argc, char **argv)
{
	Buffer b;
	Options options;
#define NUM_KEYTYPES 3
	Key *keys[NUM_KEYTYPES], *key = NULL;
	struct passwd *pw;
	int key_fd[NUM_KEYTYPES], i, found, version = 2, fd;
	u_char *signature, *data;
	char *host;
	u_int slen, dlen;
	u_int32_t rnd[256];

	/* Ensure that stdin and stdout are connected */
	if ((fd = open(_PATH_DEVNULL, O_RDWR)) < 2)
		exit(1);
	/* Leave /dev/null fd iff it is attached to stderr */
	if (fd > 2)
		close(fd);

	i = 0;
	key_fd[i++] = open(_PATH_HOST_DSA_KEY_FILE, O_RDONLY);
	key_fd[i++] = open(_PATH_HOST_ECDSA_KEY_FILE, O_RDONLY);
	key_fd[i++] = open(_PATH_HOST_RSA_KEY_FILE, O_RDONLY);

	original_real_uid = getuid();	/* XXX readconf.c needs this */
	if ((pw = getpwuid(original_real_uid)) == NULL)
		fatal("getpwuid failed");
	pw = pwcopy(pw);

	permanently_set_uid(pw);

	seed_rng();

#ifdef DEBUG_SSH_KEYSIGN
	log_init("ssh-keysign", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 0);
#endif

	/* verify that ssh-keysign is enabled by the admin */
	initialize_options(&options);
	(void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, "", &options, 0);
	fill_default_options(&options);
	if (options.enable_ssh_keysign != 1)
		fatal("ssh-keysign not enabled in %s",
		    _PATH_HOST_CONFIG_FILE);

	for (i = found = 0; i < NUM_KEYTYPES; i++) {
		if (key_fd[i] != -1)
			found = 1;
	}
	if (found == 0)
		fatal("could not open any host key");

	OpenSSL_add_all_algorithms();
	for (i = 0; i < 256; i++)
		rnd[i] = arc4random();
	RAND_seed(rnd, sizeof(rnd));

	found = 0;
	for (i = 0; i < NUM_KEYTYPES; i++) {
		keys[i] = NULL;
		if (key_fd[i] == -1)
			continue;
		keys[i] = key_load_private_pem(key_fd[i], KEY_UNSPEC,
		    NULL, NULL);
		close(key_fd[i]);
		if (keys[i] != NULL)
			found = 1;
	}
	if (!found)
		fatal("no hostkey found");

	buffer_init(&b);
	if (ssh_msg_recv(STDIN_FILENO, &b) < 0)
		fatal("ssh_msg_recv failed");
	if (buffer_get_char(&b) != version)
		fatal("bad version");
	fd = buffer_get_int(&b);
	if ((fd == STDIN_FILENO) || (fd == STDOUT_FILENO))
		fatal("bad fd");
	if ((host = get_local_name(fd)) == NULL)
		fatal("cannot get local name for fd");

	data = buffer_get_string(&b, &dlen);
	if (valid_request(pw, host, &key, data, dlen) < 0)
		fatal("not a valid request");
	free(host);

	found = 0;
	for (i = 0; i < NUM_KEYTYPES; i++) {
		if (keys[i] != NULL &&
		    key_equal_public(key, keys[i])) {
			found = 1;
			break;
		}
	}
	if (!found)
		fatal("no matching hostkey found");

	if (key_sign(keys[i], &signature, &slen, data, dlen) != 0)
		fatal("key_sign failed");
	free(data);

	/* send reply */
	buffer_clear(&b);
	buffer_put_string(&b, signature, slen);
	if (ssh_msg_send(STDOUT_FILENO, version, &b) == -1)
		fatal("ssh_msg_send failed");

	return (0);
}
Пример #3
0
int
mm_answer_keyallowed(int sock, Buffer *m)
{
	Key *key;
	char *cuser, *chost;
	u_char *blob;
	u_int bloblen;
	enum mm_keytype type = 0;
	int allowed = 0;

	debug3("%s entering", __func__);

	type = buffer_get_int(m);
	cuser = buffer_get_string(m, NULL);
	chost = buffer_get_string(m, NULL);
	blob = buffer_get_string(m, &bloblen);

	key = key_from_blob(blob, bloblen);

	if ((compat20 && type == MM_RSAHOSTKEY) ||
	    (!compat20 && type != MM_RSAHOSTKEY))
		fatal("%s: key type and protocol mismatch", __func__);

	debug3("%s: key_from_blob: %p", __func__, key);

	if (key != NULL && authctxt->valid) {
		switch (type) {
		case MM_USERKEY:
			allowed = options.pubkey_authentication &&
			    user_key_allowed(authctxt->pw, key);
			auth_method = "publickey";
			if (options.pubkey_authentication && allowed != 1)
				auth_clear_options();
			break;
		case MM_HOSTKEY:
			allowed = options.hostbased_authentication &&
			    hostbased_key_allowed(authctxt->pw,
			    cuser, chost, key);
			auth_method = "hostbased";
			break;
		case MM_RSAHOSTKEY:
			key->type = KEY_RSA1; /* XXX */
			allowed = options.rhosts_rsa_authentication &&
			    auth_rhosts_rsa_key_allowed(authctxt->pw,
			    cuser, chost, key);
			if (options.rhosts_rsa_authentication && allowed != 1)
				auth_clear_options();
			auth_method = "rsa";
			break;
		default:
			fatal("%s: unknown key type %d", __func__, type);
			break;
		}
	}
	if (key != NULL)
		key_free(key);

	/* clear temporarily storage (used by verify) */
	monitor_reset_key_state();

	if (allowed) {
		/* Save temporarily for comparison in verify */
		key_blob = blob;
		key_bloblen = bloblen;
		key_blobtype = type;
		hostbased_cuser = cuser;
		hostbased_chost = chost;
	} else {
		/* Log failed attempt */
		auth_log(authctxt, 0, auth_method, compat20 ? " ssh2" : "");
		xfree(blob);
		xfree(cuser);
		xfree(chost);
	}

	debug3("%s: key %p is %s",
	    __func__, key, allowed ? "allowed" : "not allowed");

	buffer_clear(m);
	buffer_put_int(m, allowed);
	buffer_put_int(m, forced_command != NULL);

	mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m);

	if (type == MM_RSAHOSTKEY)
		monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed);

	return (0);
}
Пример #4
0
static int
do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
    SFTP_DIRENT ***dir)
{
	Buffer msg;
	u_int count, type, id, handle_len, i, expected_id, ents = 0;
	char *handle;

	id = conn->msg_id++;

	buffer_init(&msg);
	buffer_put_char(&msg, SSH2_FXP_OPENDIR);
	buffer_put_int(&msg, id);
	buffer_put_cstring(&msg, path);
	send_msg(conn->fd_out, &msg);

	buffer_clear(&msg);

	handle = get_handle(conn->fd_in, id, &handle_len);
	if (handle == NULL)
		return(-1);

	if (dir) {
		ents = 0;
		*dir = xmalloc(sizeof(**dir));
		(*dir)[0] = NULL;
	}

	for (; !interrupted;) {
		id = expected_id = conn->msg_id++;

		debug3("Sending SSH2_FXP_READDIR I:%u", id);

		buffer_clear(&msg);
		buffer_put_char(&msg, SSH2_FXP_READDIR);
		buffer_put_int(&msg, id);
		buffer_put_string(&msg, handle, handle_len);
		send_msg(conn->fd_out, &msg);

		buffer_clear(&msg);

		get_msg(conn->fd_in, &msg);

		type = buffer_get_char(&msg);
		id = buffer_get_int(&msg);

		debug3("Received reply T:%u I:%u", type, id);

		if (id != expected_id)
			fatal("ID mismatch (%u != %u)", id, expected_id);

		if (type == SSH2_FXP_STATUS) {
			int status = buffer_get_int(&msg);

			debug3("Received SSH2_FXP_STATUS %d", status);

			if (status == SSH2_FX_EOF) {
				break;
			} else {
				error("Couldn't read directory: %s",
				    fx2txt(status));
				do_close(conn, handle, handle_len);
				xfree(handle);
				return(status);
			}
		} else if (type != SSH2_FXP_NAME)
			fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
			    SSH2_FXP_NAME, type);

		count = buffer_get_int(&msg);
		if (count == 0)
			break;
		debug3("Received %d SSH2_FXP_NAME responses", count);
		for (i = 0; i < count; i++) {
			char *filename, *longname;
			Attrib *a;

			filename = buffer_get_string(&msg, NULL);
			longname = buffer_get_string(&msg, NULL);
			a = decode_attrib(&msg);

			if (printflag)
				printf("%s\n", longname);

			if (dir) {
				*dir = xrealloc(*dir, (ents + 2) * sizeof(**dir));
				(*dir)[ents] = xmalloc(sizeof(***dir));
				(*dir)[ents]->filename = xstrdup(filename);
				(*dir)[ents]->longname = xstrdup(longname);
				memcpy(&(*dir)[ents]->a, a, sizeof(*a));
				(*dir)[++ents] = NULL;
			}

			xfree(filename);
			xfree(longname);
		}
	}

	buffer_free(&msg);
	do_close(conn, handle, handle_len);
	xfree(handle);

	/* Don't return partial matches on interrupt */
	if (interrupted && dir != NULL && *dir != NULL) {
		free_sftp_dirents(*dir);
		*dir = xmalloc(sizeof(**dir));
		**dir = NULL;
	}

	return(0);
}
Пример #5
0
/** Add a DSA key to the tspc key file
 *
 * @param dsa        the DSA param pointer filled with our key info
 * @param host       the hostname of the corresponding broker
 * @param filename   the keyfile to use
 *
 * @return  0 if error
 *          1 if ok
 *
 */
int
add_dsakey_to_keyfile(DSA *dsa, char *host, char *filename, tBoolean autoaccept)
{

  FILE *fp = NULL;
  Buffer buf;
  char *str = NULL;
  int ret = 0;

  switch (is_dsakey_in_keyfile(dsa, host, filename)) {

  case 0:
    Display(LOG_LEVEL_3, ELInfo, TSP_AUTH_PASSDSS_STRING, GOGO_STR_ERR_IN_KEY_VERIF);
    Display(LOG_LEVEL_3, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_REJECTED);
    break;
  case 1: /* not in, we add and continue */
#if defined(WIN32) && !defined(WINCE)
// When running as a service we can't ask user
// permission. Compromise and accept the key auto
//
    if (!IsService && !autoaccept)
    {
#else
    if (!autoaccept)
    {
#endif
      if (!ask(GOGO_STR_UNKNOWN_HOST_ADD_KEY, host))
      {
        Display(LOG_LEVEL_3, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_REJECTED_USER);
        break;
      }
    }
    else
  Display(LOG_LEVEL_1, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_WARN_SERVER_KEY_AUTO_ADDED);

    Display(LOG_LEVEL_2, ELInfo, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_ACCEPTED_ADDED);

    buffer_init(&buf);
    if (buf.buf == NULL)
      break;
    buffer_put_cstring(&buf, "ssh-dss");
    buffer_put_bignum(&buf, dsa->p);
    buffer_put_bignum(&buf, dsa->q);
    buffer_put_bignum(&buf, dsa->g);
    buffer_put_bignum(&buf, dsa->pub_key);

    if ( (str = pal_malloc(2 * buffer_len(&buf))) == NULL)
      break;

    if ( (base64encode(str, buffer_ptr(&buf), (int) buffer_len(&buf))) < 1)
      break;

    fp = fopen(filename, "a");
    if (fp) {
      fprintf(fp, "%s ssh-dss %s\n", host, str);
      fclose(fp);
      ret = 1;
    }
    buffer_free(&buf);
    pal_free(str);
    break;
  case 2: /* in and matching correctly, hurray */
    Display(LOG_LEVEL_2, ELInfo, TSP_AUTH_PASSDSS_STRING, GOGO_STR_MATCHING_KEY_FOUND_USED);
    ret = 1;
    break;
  case 3: /* in and NOT matching correctly */
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_WARN_STORED_LOCAL_KEY_NO_MATCH, filename, host);
  Display(LOG_LEVEL_3, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_REJECTED);
    ret = 0;
    break;
  }

  return ret;
}


/**
 * Authenticate to the Migration Broker using PASSDSS-3DES-1
 *
 * Buf_H will contain the data used to validate the server
 * signature. The data is a concatenation of the following parameters,
 * in that order:
 * azname,authname,DH_public_key,pklength,"ssh-dss",p,q,g,z,Y,ssecmask,sbuflen,dh_K
 *
 * @param socket
 * @param user
 * @param passwd
 * @param host
 * @param nt
 *
 * @return
 *
 * @todo DH public key validation  (RFC2631, 2.1.5)
 * @todo Local storage for server public keys
 *
 */
gogoc_status AuthPASSDSS_3DES_1(pal_socket_t socket, net_tools_t *nt, tConf *conf, tBrokerList **broker_list)
{
  DH   *dh = NULL;        /**< client DH key used to exchange key with server */
  DSA  *dsa = NULL; /**< Remote server DSA key public information */
  DSA_SIG *sig = NULL;    /**< DSA signature */
  char authenticate[] = "AUTHENTICATE PASSDSS-3DES-1\r\n";
  char *BufferIn  = NULL;
  char *BufferOut = NULL;
  char *BufferPtr = NULL;
  Buffer BufH;    /**< Buffer to hold data used for signature. */
  Buffer BufSpace;  /**< Space to hold data before/after base64 conversion */
  Buffer *Buf_H = &BufH;
  Buffer *Buf_Space = &BufSpace;
  BIO  *bio_rw = NULL;    /**< Memory buffer bio */
  BIO  *b64= NULL;    /**< Base64 bio */
  BIO  *cipher = NULL;    /**< Symmetric crypto bio */
  BIGNUM *server_pubkey = NULL; /**< received server public DH key */
  BIGNUM *dh_K = NULL;          /**< DH computed shared secret */
  u_char hash[20];  /**< SHA1 hash */
  u_char enc_key[24]; /**< encryption key (3des) */
  u_char enc_iv[8]; /**< initialization vector (3des) */
  u_char int_key[20]; /**< cs integrity key */
  u_char tmphash[40]; /**< temporary hash storage */
  u_char hmac[EVP_MAX_MD_SIZE]; /**< HMAC for integrity of sent data (step L) */
  int  pklength = 0;  /**< length of SSH-style DSA server public key */
  int ssecmask = 0; /**< SASL security layers offered */
  int sbuflen = 0;  /**< maximum server security layer block size */
  char *s = NULL;
  u_char num[3];    /**< Array to manupulate 3 octet number (sbuflen)  */
  /* Temporary variables */
  int  buflen, readlen, keysize, siglength;
  gogoc_status status = STATUS_SUCCESS_INIT;
  sint32_t tsp_status;

/* From draft-newman-sasl-passdss-01.  "This group was taken from the
 * ISAKMP/Oakley specification, and was originally generated by
 * Richard Schroeppel at the University of Arizona.  Properties of
 * this prime are described in [Orm96]"
 */

        /* RFC2409, DH group 2 (second Oakley group) */
  static char *dh_group2=
      "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
      "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
      "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
      "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
      "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
      "FFFFFFFF" "FFFFFFFF";
  static unsigned char dh_g[]={
    0x02,
  };


  /* Initialize Diffie Hellman variables */
  if ((dh = DH_new()) == NULL || (server_pubkey = BN_new()) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  /* Convert dh_group2 and dh_g to BIGNUM type */
  BN_hex2bn(&dh->p, dh_group2);
  dh->g = BN_bin2bn(dh_g,sizeof(dh_g),NULL);
  if ((dh->p == NULL) || (dh->g == NULL))
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_INITIALIZATION_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
  }
  if ((dh_K = BN_new()) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }

  /* Reserve storage for DSA key */
  if ((dsa = DSA_new()) == NULL || (dsa->p = BN_new()) == NULL ||
      (dsa->q = BN_new()) == NULL ||  (dsa->g = BN_new()) == NULL ||
      (dsa->pub_key = BN_new()) == NULL || (dsa->priv_key = BN_new()) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }

  /* Allocate memory for DSA signature */
  if ((sig = DSA_SIG_new()) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  /* Initialize data buffers */
  BufferIn  = calloc(1, TSP_AUTH_PASSDSS_BUFFERSIZE);
  BufferOut = calloc(1, TSP_AUTH_PASSDSS_BUFFERSIZE);

  if ((BufferIn == NULL) || (BufferOut == NULL))
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  buffer_init(Buf_Space);
  buffer_init(Buf_H);
  if (Buf_Space->buf == NULL || Buf_H->buf == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  /* Create a read/write memory BIO. Memory is segment is
   * created and resized as needed. When BIO is destroyed, the
   * memory is freed. */
  bio_rw = BIO_new(BIO_s_mem());
  /* Create a base64 BIO filter */
  b64 = BIO_new(BIO_f_base64());
  if ((bio_rw == NULL) || (b64 == NULL))
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }

  /*
    Compute the Diffie-Hellman public value "X" as follows.  If
    X has a value of 0, repeat.

         x
    X = g  mod n

    where g = dh_g = 2
          n = dh_group2
    x = DH secret key
    X = DH public key
  */
  if (DH_generate_key(dh) == 0)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_DH_GEN_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
  }

  /* Validate DH public key (RFC2631, 2.1.5) */

  /* Send  message with SASL mechanism identifier */
  if ( nt->netsend(socket, authenticate, sizeof(authenticate)) == -1 )
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_NET_FAIL_W_SOCKET);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO);
    goto error;
  }

  /* First PASSDSS  message from client to server:
     string azname       ; the user name to login as, may be empty if
                           same as authentication name
     string authname     ; the authentication name
     mpint  X            ; Diffie-Hellman parameter X
  */
  /* azname is empty. Just insert a string length zero */
  buffer_put_int(Buf_Space, 0);
  /* authname */
  buffer_put_cstring(Buf_Space, conf->userid);
  /* DH public key */
  buffer_put_bignum(Buf_Space, dh->pub_key);

  /* At this point, save the buffer into Buf_H. Used later for
   * signature verification. */
  buffer_append(Buf_H, buffer_ptr(Buf_Space), buffer_len(Buf_Space));

  /* Push base64 filter */
  BIO_push(b64, bio_rw);
  /* no newline */
  BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
  /* Write Buffer content into bio_rw. Buffer will be base64
   * encoded. */
  BIO_write(b64, buffer_ptr(Buf_Space), (int) buffer_len(Buf_Space));
  BIO_flush(b64);
  /* Get pointer to the result */
  buflen = BIO_get_mem_data(bio_rw, &BufferPtr);

  // Send data to server, save response in BufferIn.
  if((readlen = nt->netsendrecv(socket,
               BufferPtr, buflen,
               BufferIn, TSP_AUTH_PASSDSS_BUFFERSIZE)) == -1)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_NET_FAIL_RW_SOCKET);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO);
    goto error;
  }
  /* remove base64 filter */
  BIO_pop(bio_rw);
  buffer_clear(Buf_Space);
  buflen = 0;

  /* Decode response (base64) and extract server response
   *
   * The response format is as follows:

       uint32   pklength   ; length of SSH-style DSA server public key
           (number of bytes up to y, inclusively)
         string "ssh-dss"  ; constant string "ssh-dss" (lower case)
         mpint  p          ; DSA public key parameters
         mpint  q
         mpint  g
         mpint  z            (y in draft)
       mpint    Y          ; Diffie-Hellman parameter Y
       OCTET    ssecmask   ; SASL security layers offered
       3 OCTET  sbuflen    ; maximum server security layer block size
       uint32   siglength  ; length of SSH-style dss signature
           (number of bytes up to s inclusively)
         string "ssh-dss"  ; constant string "ssh-dss" (lower case)
         mpint  r          ; DSA signature parameters
         mpint  s

   */

  buflen = base64decode(BufferOut, BufferIn);

  buffer_append(Buf_Space, BufferOut, buflen);
  /* Get pklength */
  pklength = buffer_get_int(Buf_Space);
  /* Assuming that
   * p, g, and y are 512 bits,
   * q is 160 bits,
   * "ssh-dss" is 7 bytes
   * pklength should be at least 240 bytes.
   */
  if (pklength < 240)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_RCVD_DATA_INVALID);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
  }

  /* Make a copy of (pklength|"ssh-dss"|p|q|g|z) in Buf_H */
  /* Add pklength */
  buffer_put_int(Buf_H, pklength);
  /* Add "ssh-dss"|p|q|g|z */
  buffer_append(Buf_H, buffer_ptr(Buf_Space), pklength);

  /* Get "ssh-dss" string */
  s = buffer_get_string(Buf_Space, (unsigned int*)&buflen);
  pal_free(s); s = NULL;
  /* Get p */
  buffer_get_bignum(Buf_Space, dsa->p);
  /* Get q */
  buffer_get_bignum(Buf_Space, dsa->q);
  /* Get g */
  buffer_get_bignum(Buf_Space, dsa->g);
  /* Get z (pub_key) */
  buffer_get_bignum(Buf_Space, dsa->pub_key);
  /* Get DH public key */
  buffer_get_bignum(Buf_Space, server_pubkey);
  /* Copy in Buf_H for signature verification later */
  buffer_put_bignum(Buf_H, server_pubkey);

  /* Buffer now points at ssecmask (1 octet), followed by
   * sbuflen (3 octets). Make a copy of these 4 octets in Buf_H
   * now, then extract these values. */
  buffer_append(Buf_H, buffer_ptr(Buf_Space), 4);

  /* Get ssecmask */
  ssecmask = buffer_get_octet(Buf_Space);
  /* Get sbuflen
   * Big endian binary unsigned integer */
  buffer_get(Buf_Space, (char *)num, 3);
  sbuflen =  (((u_long)(u_char)(num)[0] << 16) |
        ((u_long)(u_char)(num)[1] << 8) |
        ((u_long)(u_char)(num)[2]));

  /* DSS signature */
  /* Get siglength */
  siglength = buffer_get_int(Buf_Space);
  /* r and s are 20 bytes each, encoded as mpint (2*24)
   * "ssh-dss" is 7 bytes + int32 siglength should be >= 59
   * octets (mpint may have leading zero byte)
   */
  if (siglength < 59)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_RCVD_DATA_INVALID);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
  }
  /* Get "ssh-dss" string */
  s = buffer_get_string(Buf_Space, (unsigned int*)&buflen);
  pal_free(s); s = NULL;
  /* Get DSA signature r and s*/
  if ((sig->r= BN_new()) == NULL || (sig->s = BN_new()) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  /* Get r */
  buffer_get_bignum(Buf_Space, sig->r);
  /* Get s */
  buffer_get_bignum(Buf_Space, sig->s);

  /* Validate server DH public key  (RFC2631, 2.1.5) */

  {
    if( !add_dsakey_to_keyfile(dsa, conf->server, TSPC_DSA_KEYFILE, conf->no_questions) )
    {
      Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_KEY_VERIF_ERROR);
      status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
      goto error;
    }
  }

  /* Verify that DSA public key belongs to server */

  /* Compute DH shared secret */
  if ((s = calloc(1, DH_size(dh))) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  if( (keysize = DH_compute_key((unsigned char*)s, server_pubkey, dh)) < 0 )
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_DH_SHARED_COMPUTE_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
  }
  BN_bin2bn((const unsigned char*)s, keysize, dh_K);
  memset(s, 0, keysize);
  pal_free(s);
  s = NULL;
  Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
    GOGO_STR_DH_SHARED_KEY, BN_bn2hex(dh_K));

  /* Append dh_K in to complete the buffer. Use Buffer to hold
   * result to keep Bf_H intact, since to will be used (without
   * dh_K) to compute HMAC for packet integrity. */
  buffer_clear(Buf_Space);
  buffer_append(Buf_Space, buffer_ptr(Buf_H), buffer_len(Buf_H));
  buffer_put_bignum(Buf_Space, dh_K);

  /* Compute SHA1 hash of Buffer */
  SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), hash);

  /* Debug information available at level 4 */
 {
   BIGNUM *h;
   h = BN_bin2bn(hash, 20, NULL);
   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_SIGNED_HASH, BN_bn2hex(h));
   BN_free(h);
 }
   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_DSA_SIGN_R, BN_bn2hex(sig->r));
   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_DSA_SIGN_S, BN_bn2hex(sig->s));

  // Verify that the DSS signature is a signature of hash.
  switch( DSA_do_verify(hash, sizeof(hash), sig, dsa) )
  {
  case 0:
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_BAD_SIG_FROM_SERVER);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
    break; /* NOTREACHED */

  case 1:  /* correct signature */
    break;

  default: /* -1 on error */
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SIG_VERIF_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
    break; /* NOTREACHED */
  }

  /* Step I: Compute 3DES key and iv */
  /*
    cs-encryption-iv    = SHA1( K || "A" || H )
    sc-encryption-iv    = SHA1( K || "B" || H )
    cs-encryption-key-1 = SHA1( K || "C" || H )
    cs-encryption-key-2 = SHA1( K || cs-encryption-key-1 )
    cs-encryption-key   = cs-encryption-key-1 || cs-encryption-key-2
    sc-encryption-key-1 = SHA1( K || "D" || H )
    sc-encryption-key-2 = SHA1( K || sc-encryption-key-1 )
    sc-encryption-key   = sc-encryption-key-1 || sc-encryption-key-2
    cs-integrity-key    = SHA1( K || "E" || H )
    sc-integrity-key    = SHA1( K || "F" || H )

    K is dh_k in mpint format (string)
    H is hash
  */

  /* Since we won't support SASL security layers, we need to
   * compute the following only:
   * cs-encryption-iv
   * cs-encryption-key
   * cs-integrity-key
   */
  buffer_clear(Buf_Space);
  buffer_put_bignum(Buf_Space, dh_K);
  buffer_put_octet(Buf_Space,'A');
  buffer_append(Buf_Space, hash, 20);
  SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), tmphash);
  /* Use first 8 octets as iv */
  memcpy(enc_iv, tmphash, 8);

  buffer_clear(Buf_Space);
  buffer_put_bignum(Buf_Space, dh_K);
  buffer_put_octet(Buf_Space,'E');
  buffer_append(Buf_Space, hash, 20);
  SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), int_key);

  buffer_clear(Buf_Space);
  buffer_put_bignum(Buf_Space, dh_K);
  buffer_put_octet(Buf_Space,'C');
  buffer_append(Buf_Space, hash, 20);
  SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), tmphash);
  buffer_clear(Buf_Space);
  buffer_put_bignum(Buf_Space, dh_K);
  buffer_append(Buf_Space, tmphash, 20);
  SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), tmphash+20);
  /* Use first 24 octets as key */
  memcpy(enc_key, tmphash, 24);
 {
   BIGNUM *enc, *i, *iv;
   enc = BN_bin2bn(enc_key, 24, NULL);
   iv = BN_bin2bn(enc_iv, 8, NULL);
   i = BN_bin2bn(int_key, 20, NULL);

   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_PASSDS_ENC_KEY, BN_bn2hex(enc));
   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_PASSDS_IV, BN_bn2hex(iv));
   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_PASSDS_INTEG_KEY, BN_bn2hex(i));
   BN_free(enc);
   BN_free(i);
   BN_free(iv);
 }
  /*
    (J) Create a buffer beginning with a bit mask for the
    selected security layer (it MUST be one offered from server)
    followed by three octets representing the maximum
    cipher-text buffer size (at least 32) the client can accept
    in network byte order.  This is followed by a string
    containing the passphrase.
  */
  buffer_clear(Buf_Space);
  buffer_put_octet(Buf_Space, ssecmask);
  buffer_put_octet(Buf_Space, 0);
  buffer_put_octet(Buf_Space, 0);
  buffer_put_octet(Buf_Space, 0); /**< @bug must be at least 32 */
  buffer_put_cstring(Buf_Space, conf->passwd);

  /*
    (K) Create a buffer containing items (1) through (7)
    immediately followed by the first four octets of (J).
  */
  buffer_append(Buf_H, buffer_ptr(Buf_Space), 4);

  /*
    (L) Compute HMAC-SHA-1 with (K) as the data and the
    cs-integrity- key from step (I) as the key.  This produces a
    20 octet result.
  */
  HMAC(EVP_sha1(), int_key, sizeof(int_key),
       buffer_ptr(Buf_H), buffer_len(Buf_H), hmac, (unsigned int*)&keysize);
  /*
    (M) Create a buffer containing (J) followed by (L) followed
    by an arbitrary number of zero octets as necessary to reach
    the block size of DES and conceal the passphrase length from
    an eavesdropper.
  */
  buffer_append(Buf_Space, hmac, keysize);

  /*
    (N) Apply the triple-DES algorithm to (M) with the first 8
    octets of cs-encryption-iv from step (I) as the
    initialization vector and the first 24 octets of
    cs-encryption-key as the key.
  */
  /*
    Padding is automatically done. From OpenSSL EVP_EncryptInit(3):
    EVP_CIPHER_CTX_set_padding() enables or disables padding. By default
    encryption operations are padded using standard block padding and the
    padding is checked and removed when decrypting.
  */

  /*
    Create BIO filter to encrypt using 3des + convert to
    base64. Result is written in memory BIO.
  */
  /* Erase BIO and buffer memory */
  BIO_reset(bio_rw);
  memset(BufferOut, 0, TSP_AUTH_PASSDSS_BUFFERSIZE);
  memset(BufferIn, 0, TSP_AUTH_PASSDSS_BUFFERSIZE);
  buflen = 0;

  /* Create cipher BIO */
  cipher = BIO_new(BIO_f_cipher());
  BIO_set_cipher(cipher, EVP_des_ede3_cbc(), enc_key, enc_iv, 1);
  /* Assemble filters as cipher->b64->bio_rw */
  BIO_push(cipher, b64);
  BIO_push(b64, bio_rw);

  /* Write Buffer content into bio_rw */
  BIO_write(cipher, buffer_ptr(Buf_Space), (int) buffer_len(Buf_Space));
  BIO_flush(cipher);
  /* Get pointer to the result. */
  buflen = BIO_get_mem_data(bio_rw, &BufferPtr);

  /* wipe encryption material */
  memset(enc_key, 0, sizeof(enc_key));
  memset(enc_iv, 0, sizeof(enc_iv));

  /* Send data to server, save response in BufferIn */
  if( (readlen = nt->netsendrecv(socket, BufferPtr, buflen,
       BufferIn, TSP_AUTH_PASSDSS_BUFFERSIZE)) == -1)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_NET_FAIL_RW_SOCKET);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO);
    goto error;
  }
  tsp_status = tspGetStatusCode(BufferIn);

  // Check if the reply status indicated a broker redirection.
  if( tspIsRedirectStatus(tsp_status) )
  {
    if( tspHandleRedirect(BufferIn, conf, broker_list) == TSP_REDIRECT_OK )
    {
      status = make_status(CTX_TSPAUTHENTICATION, EVNT_BROKER_REDIRECTION);
    }
    else
    {
      // Redirect error.
      status = make_status(CTX_TSPAUTHENTICATION, ERR_BROKER_REDIRECTION);
    }
    goto error;
  }

  // Check if authentication was successful.
  switch( tsp_status )
  {
  case TSP_PROTOCOL_SUCCESS:
    break;

  case TSP_PROTOCOL_AUTH_FAILED:
    Display(LOG_LEVEL_1, ELError, "AuthPASSDSS_3DES_1", STR_TSP_AUTH_FAILED_USER, conf->userid);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;

  default:
    Display(LOG_LEVEL_1, ELError, "AuthPASSDSS_3DES_1", STR_TSP_UNKNOWN_ERR_AUTH_FAILED, tspGetTspStatusStr(tsp_status));
    status = make_status(CTX_TSPAUTHENTICATION, ERR_TSP_GENERIC_ERROR);
    goto error;
  }

  status = STATUS_SUCCESS_INIT;

 error:

  /* Free storage for DSA key */
  if (dsa != NULL) DSA_free(dsa); /* Also frees BIGNUMs inside struct */
  /* DSA signature */
  if (sig != NULL) DSA_SIG_free(sig);
  /* Free Diffie Hellman variables */
  if (dh != NULL) DH_free(dh); /* Also frees BIGNUMs inside struct */
  if (server_pubkey != NULL) BN_free(server_pubkey);
  if (dh_K != NULL) BN_free(dh_K);
  /* Buffers */
  if (Buf_Space->buf != NULL) buffer_free(Buf_Space);
  if (Buf_H->buf != NULL)  buffer_free(Buf_H);
  /* malloc'ed space*/
  if (BufferIn != NULL) pal_free(BufferIn);
  if (BufferOut != NULL) pal_free(BufferOut);
  /* BIOs */
  if (cipher != NULL) BIO_vfree(cipher);
  if (b64 != NULL) BIO_vfree(b64);
  if (bio_rw != NULL) BIO_vfree(bio_rw);
  /* strings buffers */
  if (s != NULL) pal_free(s);

  return status;
}
Пример #6
0
void
mm_get_keystate(struct monitor *pmonitor)
{
	Buffer m;
	u_char *blob, *p;
	u_int bloblen, plen;
	u_int32_t seqnr, packets;
	u_int64_t blocks, bytes;

	debug3("%s: Waiting for new keys", __func__);

	buffer_init(&m);
	mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, &m);
	if (!compat20) {
		child_state.ssh1protoflags = buffer_get_int(&m);
		child_state.ssh1cipher = buffer_get_int(&m);
		child_state.ssh1key = buffer_get_string(&m,
		    &child_state.ssh1keylen);
		child_state.ivout = buffer_get_string(&m,
		    &child_state.ivoutlen);
		child_state.ivin = buffer_get_string(&m, &child_state.ivinlen);
		goto skip;
	} else {
		/* Get the Kex for rekeying */
		*pmonitor->m_pkex = mm_get_kex(&m);
	}

	blob = buffer_get_string(&m, &bloblen);
	current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen);
	xfree(blob);

	debug3("%s: Waiting for second key", __func__);
	blob = buffer_get_string(&m, &bloblen);
	current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen);
	xfree(blob);

	/* Now get sequence numbers for the packets */
	seqnr = buffer_get_int(&m);
	blocks = buffer_get_int64(&m);
	packets = buffer_get_int(&m);
	bytes = buffer_get_int64(&m);
	packet_set_state(MODE_OUT, seqnr, blocks, packets, bytes);
	seqnr = buffer_get_int(&m);
	blocks = buffer_get_int64(&m);
	packets = buffer_get_int(&m);
	bytes = buffer_get_int64(&m);
	packet_set_state(MODE_IN, seqnr, blocks, packets, bytes);

 skip:
	/* Get the key context */
	child_state.keyout = buffer_get_string(&m, &child_state.keyoutlen);
	child_state.keyin  = buffer_get_string(&m, &child_state.keyinlen);

	debug3("%s: Getting compression state", __func__);
	/* Get compression state */
	p = buffer_get_string(&m, &plen);
	if (plen != sizeof(child_state.outgoing))
		fatal("%s: bad request size", __func__);
	memcpy(&child_state.outgoing, p, sizeof(child_state.outgoing));
	xfree(p);

	p = buffer_get_string(&m, &plen);
	if (plen != sizeof(child_state.incoming))
		fatal("%s: bad request size", __func__);
	memcpy(&child_state.incoming, p, sizeof(child_state.incoming));
	xfree(p);

	/* Network I/O buffers */
	debug3("%s: Getting Network I/O buffers", __func__);
	child_state.input = buffer_get_string(&m, &child_state.ilen);
	child_state.output = buffer_get_string(&m, &child_state.olen);

	/* Roaming */
	if (compat20) {
		child_state.sent_bytes = buffer_get_int64(&m);
		child_state.recv_bytes = buffer_get_int64(&m);
	}

	buffer_free(&m);
}
Пример #7
0
Файл: t-tr.c Проект: AnthraX1/rk
Boolean handler_input(Handler c)
{
  SshBuffer *packet;
  char *cp, *cp2;
  int len;
  unsigned char byte;
  Boolean wake_up_output = FALSE;

  for (;; c->script++)
    {
#ifdef DEBUG
      ssh_debug("%s: handler_input: %s", c->side, opnames[c->script->op]);
#endif
      switch (c->script->op)
        {
        case OP_EXPECT_SERVICE_REQUEST:
          packet = handler_input_expect_cross(c,
                                              SSH_CROSS_SERVICE_REQUEST);
          if (!packet)
            return FALSE;
          cp = buffer_get_uint32_string(packet, NULL);
          if (strcmp(cp, c->script->arg) != 0)
            ssh_fatal("%s: handler_input: service request mismatch: %s vs %s",
                  c->side, c->script->arg, cp);
          ssh_xfree(cp);
          ssh_buffer_free(packet);
          break;

        case OP_EXPECT_DISCONNECT:
          packet = handler_input_expect_cross(c, SSH_CROSS_DISCONNECT);
          if (!packet)
            return FALSE;
          (void)buffer_get_boolean(packet);
          (void)buffer_get_int(packet);
          cp = buffer_get_uint32_string(packet, NULL);
          ssh_xfree(buffer_get_uint32_string(packet, NULL)); /* lang. tag */
          if (strcmp(cp, c->script->arg) != 0)
            ssh_fatal("%s: handler_input: disconnect mismatch: %s vs %s",
                  c->side, c->script->arg, cp);
          ssh_xfree(cp);
          ssh_buffer_free(packet);
          break;
          
        case OP_EXPECT_EOF:
          len = ssh_stream_read(c->stream, &byte, 1);
          if (len < 0)
            return FALSE;
          if (len != 0)
            ssh_fatal("%s: handler_input: EOF expected, received 0x%0x",
                  c->side, byte);
          break;
          
        case OP_EXPECT_STARTUP:
          packet = handler_input_expect_cross(c, SSH_CROSS_STARTUP);
          if (!packet)
            return FALSE;
          ssh_buffer_free(packet);
          break;
          
        case OP_EXPECT_ALGORITHMS:
          packet = handler_input_expect_cross(c, SSH_CROSS_ALGORITHMS);
          if (!packet)
            return FALSE;
          ssh_buffer_free(packet);
          break;

        case OP_EXPECT_PACKET:
          packet = handler_input_expect_packet(c, atoi(c->script->arg));
          if (!packet)
            return FALSE;
          ssh_buffer_free(packet);
          break;
          
        case OP_EXPECT_TEST_STREAM:
          while (c->stream_offset < ssh_buffer_len(&testdata))
            {
              packet = handler_input_expect_packet(c, atoi(c->script->arg));
              if (!packet)
                return FALSE;
              cp = ssh_buffer_ptr(packet);
              cp2 = ssh_buffer_ptr(&testdata);
              if (memcmp(cp, cp2 + c->stream_offset, ssh_buffer_len(packet)) != 0)
                ssh_fatal("%s: handler_input: TEST_STREAM compare fail offset %d",
                      c->side, c->stream_offset);
              c->stream_offset += ssh_buffer_len(packet);
              ssh_buffer_free(packet);
            }
          c->stream_offset = 0;
          break;
          
        case OP_SEND_SERVICE_ACCEPT:
        case OP_SEND_REKEY_REQUEST:
        case OP_SEND_PACKET:
        case OP_SEND_TEST_STREAM:
        case OP_SEND_DISCONNECT:
        case OP_SEND_EOF:
          wake_up_output = TRUE;
          goto out;

        case OP_END:
          return FALSE;

        default:
          ssh_fatal("%s: handler_input: unknown op %d",
                c->side, (int)c->script->op);
        }
    }
out:
  c->input_blocked = TRUE;
  return wake_up_output;
}
Пример #8
0
int
wav_scan(ScanData s)
{
  int ret = 1;
  Buffer buf;
  uint32_t chunk_size;
  
  buffer_init(&buf, BLOCK_SIZE);
  
  if ( !buffer_check_load(&buf, s->fp, 12, BLOCK_SIZE) ) {
    ret = 0;
    goto out;
  }
  
  if ( !strncmp( (char *)buffer_ptr(&buf), "RIFF", 4 ) ) {
    // We've got a RIFF file
    buffer_consume(&buf, 4);
  
    chunk_size = buffer_get_int_le(&buf);
    
    // Check format
    if ( strncmp( (char *)buffer_ptr(&buf), "WAVE", 4 ) ) {
      LOG_ERROR("Invalid WAV file: missing WAVE header: %s\n", s->path);
      ret = 0;
      goto out;
    }
    
    buffer_consume(&buf, 4);
    
    _parse_wav(s, &buf);
  }
  else if ( !strncmp( (char *)buffer_ptr(&buf), "FORM", 4 ) ) {
    // We've got an AIFF file
    char *bptr;
    
    buffer_consume(&buf, 4);
    
    chunk_size = buffer_get_int(&buf);
    
    // Check format
    bptr = buffer_ptr(&buf);
    if ( bptr[0] == 'A' && bptr[1] == 'I' && bptr[2] == 'F' && (bptr[3] == 'F' || bptr[3] == 'C') ) {
      buffer_consume(&buf, 4);

      //_parse_aiff(s, &buf);
    }
    else {
      LOG_ERROR("Invalid AIFF file: missing AIFF header: %s\n", s->path);
      ret = 0;
      goto out;
    }
  }
  else {
    LOG_ERROR("Invalid WAV file: missing RIFF header: %s\n", s->path);
    ret = 0;
    goto out;
  }
  
out:
  buffer_free(&buf);
  
  return ret;
}
Пример #9
0
int
main(int argc, char **argv)
{
	Buffer b;
	Options options;
	Key *keys[2], *key;
	struct passwd *pw;
	int key_fd[2], i, found, version = 2, fd;
	u_char *signature, *data;
	char *host;
	u_int slen, dlen;
	u_int32_t rnd[256];

	key_fd[0] = open(_PATH_HOST_RSA_KEY_FILE, O_RDONLY);
	key_fd[1] = open(_PATH_HOST_DSA_KEY_FILE, O_RDONLY);

	seteuid(getuid());
	setuid(getuid());

	init_rng();
	seed_rng();
	arc4random_stir();

#ifdef DEBUG_SSH_KEYSIGN
	log_init("ssh-keysign", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 0);
#endif

	/* verify that ssh-keysign is enabled by the admin */
	original_real_uid = getuid();	/* XXX readconf.c needs this */
	initialize_options(&options);
	(void)read_config_file(_PATH_HOST_CONFIG_FILE, "", &options);
	fill_default_options(&options);
	if (options.enable_ssh_keysign != 1)
		fatal("ssh-keysign not enabled in %s",
		    _PATH_HOST_CONFIG_FILE);

	if (key_fd[0] == -1 && key_fd[1] == -1)
		fatal("could not open any host key");

	if ((pw = getpwuid(getuid())) == NULL)
		fatal("getpwuid failed");
	pw = pwcopy(pw);

	SSLeay_add_all_algorithms();
	for (i = 0; i < 256; i++)
		rnd[i] = arc4random();
	RAND_seed(rnd, sizeof(rnd));

	found = 0;
	for (i = 0; i < 2; i++) {
		keys[i] = NULL;
		if (key_fd[i] == -1)
			continue;
		keys[i] = key_load_private_pem(key_fd[i], KEY_UNSPEC,
		    NULL, NULL);
		close(key_fd[i]);
		if (keys[i] != NULL)
			found = 1;
	}
	if (!found)
		fatal("no hostkey found");

	buffer_init(&b);
	if (ssh_msg_recv(STDIN_FILENO, &b) < 0)
		fatal("ssh_msg_recv failed");
	if (buffer_get_char(&b) != version)
		fatal("bad version");
	fd = buffer_get_int(&b);
	if ((fd == STDIN_FILENO) || (fd == STDOUT_FILENO))
		fatal("bad fd");
	if ((host = get_local_name(fd)) == NULL)
		fatal("cannot get sockname for fd");

	data = buffer_get_string(&b, &dlen);
	if (valid_request(pw, host, &key, data, dlen) < 0)
		fatal("not a valid request");
	xfree(host);

	found = 0;
	for (i = 0; i < 2; i++) {
		if (keys[i] != NULL &&
		    key_equal(key, keys[i])) {
			found = 1;
			break;
		}
	}
	if (!found)
		fatal("no matching hostkey found");

	if (key_sign(keys[i], &signature, &slen, data, dlen) != 0)
		fatal("key_sign failed");
	xfree(data);

	/* send reply */
	buffer_clear(&b);
	buffer_put_string(&b, signature, slen);
	ssh_msg_send(STDOUT_FILENO, version, &b);

	return (0);
}
Пример #10
0
int
mm_answer_keyallowed(int sock, Buffer *m)
{
	struct sshkey *key;
	char *cuser, *chost;
	u_char *blob;
	u_int bloblen, pubkey_auth_attempt;
	enum mm_keytype type = 0;
	int allowed = 0;

	debug3("%s entering", __func__);

	type = buffer_get_int(m);
	cuser = buffer_get_string(m, NULL);
	chost = buffer_get_string(m, NULL);
	blob = buffer_get_string(m, &bloblen);
	pubkey_auth_attempt = buffer_get_int(m);

	key = key_from_blob(blob, bloblen);

	debug3("%s: key_from_blob: %p", __func__, key);

	if (key != NULL && authctxt->valid) {
		/* These should not make it past the privsep child */
		if (key_type_plain(key->type) == KEY_RSA &&
		    (datafellows & SSH_BUG_RSASIGMD5) != 0)
			fatal("%s: passed a SSH_BUG_RSASIGMD5 key", __func__);

		switch (type) {
		case MM_USERKEY:
			allowed = options.pubkey_authentication &&
			    !auth2_key_already_used(authctxt, key) &&
			    match_pattern_list(sshkey_ssh_name(key),
			    options.pubkey_key_types, 0) == 1 &&
			    user_key_allowed(authctxt->pw, key,
			    pubkey_auth_attempt);
			auth_method = "publickey";
			if (options.pubkey_authentication &&
			    (!pubkey_auth_attempt || allowed != 1))
				auth_clear_options();
			break;
		case MM_HOSTKEY:
			allowed = options.hostbased_authentication &&
			    !auth2_key_already_used(authctxt, key) &&
			    match_pattern_list(sshkey_ssh_name(key),
			    options.hostbased_key_types, 0) == 1 &&
			    hostbased_key_allowed(authctxt->pw,
			    cuser, chost, key);
			auth2_record_info(authctxt,
			    "client user \"%.100s\", client host \"%.100s\"",
			    cuser, chost);
			auth_method = "hostbased";
			break;
		default:
			fatal("%s: unknown key type %d", __func__, type);
			break;
		}
	}

	debug3("%s: key is %s", __func__, allowed ? "allowed" : "not allowed");

	auth2_record_key(authctxt, 0, key);
	sshkey_free(key);

	/* clear temporarily storage (used by verify) */
	monitor_reset_key_state();

	if (allowed) {
		/* Save temporarily for comparison in verify */
		key_blob = blob;
		key_bloblen = bloblen;
		key_blobtype = type;
		hostbased_cuser = cuser;
		hostbased_chost = chost;
	} else {
		/* Log failed attempt */
		auth_log(authctxt, 0, 0, auth_method, NULL);
		free(blob);
		free(cuser);
		free(chost);
	}

	buffer_clear(m);
	buffer_put_int(m, allowed);
	buffer_put_int(m, forced_command != NULL);

	mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m);

	return (0);
}
Пример #11
0
void
_parse_aiff(PerlIO *infile, Buffer *buf, char *file, uint32_t file_size, HV *info, HV *tags)
{
  uint32_t offset = 12;
  
  while ( offset < file_size - 8 ) {
    char chunk_id[5];
    int chunk_size;
    
    // Verify we have at least 8 bytes
    if ( !_check_buf(infile, buf, 8, WAV_BLOCK_SIZE) ) {
      return;
    }
    
    strncpy( chunk_id, (char *)buffer_ptr(buf), 4 );
    chunk_id[4] = '\0';
    buffer_consume(buf, 4);
    
    chunk_size = buffer_get_int(buf);
    
    // Adjust for padding
    if ( chunk_size % 2 ) {
      chunk_size++;
    }
    
    offset += 8;
    
    DEBUG_TRACE("%s size %d\n", chunk_id, chunk_size);
    
    // Seek past SSND, everything else we parse
    // XXX: Are there other large chunks we should ignore?
    if ( !strcmp( chunk_id, "SSND" ) ) {
      my_hv_store( info, "audio_offset", newSVuv(offset) );
      my_hv_store( info, "audio_size", newSVuv(chunk_size) );

      // Seek past data if there are more chunks after it
      if ( file_size > offset + chunk_size ) {
        PerlIO_seek(infile, offset + chunk_size, SEEK_SET);
      }
      
      buffer_clear(buf);
    }
    else if ( !strcmp( chunk_id, "id3 " ) || !strcmp( chunk_id, "ID3 " ) || !strcmp( chunk_id, "ID32" ) ) {
      // Read header to verify version
      unsigned char *bptr = buffer_ptr(buf);
      
      if (
        (bptr[0] == 'I' && bptr[1] == 'D' && bptr[2] == '3') &&
        bptr[3] < 0xff && bptr[4] < 0xff &&
        bptr[6] < 0x80 && bptr[7] < 0x80 && bptr[8] < 0x80 && bptr[9] < 0x80
      ) {        
        // Start parsing ID3 from offset
        parse_id3(infile, file, info, tags, offset, file_size);
      }
      
      // Seen ID3 chunks with the chunk size in little-endian instead of big-endian
      if (chunk_size < 0 || offset + chunk_size > file_size) {
        break;
      }
      
      // Seek past ID3 and clear buffer
      DEBUG_TRACE("Seeking past ID3 to %d\n", offset + chunk_size);
      PerlIO_seek(infile, offset + chunk_size, SEEK_SET);
      buffer_clear(buf);
    }
    else {
      // Make sure we have enough data
      if ( !_check_buf(infile, buf, chunk_size, WAV_BLOCK_SIZE) ) {
        return;
      }
      
      if ( !strcmp( chunk_id, "COMM" ) ) {
        _parse_aiff_comm(buf, chunk_size, info);
      }
      else if ( !strcmp( chunk_id, "PEAK" ) ) {
        _parse_wav_peak(buf, chunk_size, info, 1);
      }
      else {
        PerlIO_printf(PerlIO_stderr(), "Unhandled AIFF chunk %s size %d (skipped)\n", chunk_id, chunk_size);
        buffer_consume(buf, chunk_size);
      }
    }
    
    offset += chunk_size;
  }
}
Пример #12
0
static int
get_wav_metadata(PerlIO *infile, char *file, HV *info, HV *tags)
{
  Buffer buf;
  off_t file_size;
  int err = 0;
  uint32_t chunk_size;
  
  file_size = _file_size(infile);
  
  buffer_init(&buf, WAV_BLOCK_SIZE);
  
  if ( !_check_buf(infile, &buf, 12, WAV_BLOCK_SIZE) ) {
    err = -1;
    goto out;
  }
  
  if ( !strncmp( (char *)buffer_ptr(&buf), "RIFF", 4 ) ) {
    // We've got a RIFF file
    buffer_consume(&buf, 4);
  
    chunk_size = buffer_get_int_le(&buf);
    
    // Check format
    if ( strncmp( (char *)buffer_ptr(&buf), "WAVE", 4 ) ) {
      PerlIO_printf(PerlIO_stderr(), "Invalid WAV file: missing WAVE header: %s\n", file);
      err = -1;
      goto out;
    }
    
    buffer_consume(&buf, 4);
    
    my_hv_store( info, "file_size", newSVuv(file_size) );
    
    _parse_wav(infile, &buf, file, file_size, info, tags);
  }
  else if ( !strncmp( (char *)buffer_ptr(&buf), "FORM", 4 ) ) {
    // We've got an AIFF file
    char *bptr;
    
    buffer_consume(&buf, 4);
    
    chunk_size = buffer_get_int(&buf);
    
    // Check format
    bptr = buffer_ptr(&buf);
    if ( bptr[0] == 'A' && bptr[1] == 'I' && bptr[2] == 'F' && (bptr[3] == 'F' || bptr[3] == 'C') ) {
      buffer_consume(&buf, 4);

      my_hv_store( info, "file_size", newSVuv(file_size) );

      _parse_aiff(infile, &buf, file, file_size, info, tags);
    }
    else {
      PerlIO_printf(PerlIO_stderr(), "Invalid AIFF file: missing AIFF header: %s\n", file);
      err = -1;
      goto out;
    }
  }
  else {
    PerlIO_printf(PerlIO_stderr(), "Invalid WAV file: missing RIFF header: %s\n", file);
    err = -1;
    goto out;
  }
  
out:
  buffer_free(&buf);

  if (err) return err;

  return 0;
}
Пример #13
0
static Key *
key_load_private_rsa1(int fd, const char *filename, const char *passphrase,
                      char **commentp)
{
    int i, check1, check2, cipher_type;
    off_t len;
    Buffer buffer, decrypted;
    u_char *cp;
    CipherContext ciphercontext;
    Cipher *cipher;
    Key *prv = NULL;
    struct stat st;

    if (fstat(fd, &st) < 0) {
        error("fstat for key file %.200s failed: %.100s",
              filename, strerror(errno));
        close(fd);
        return NULL;
    }
    len = st.st_size;

    buffer_init(&buffer);
    cp = buffer_append_space(&buffer, len);

    if (read(fd, cp, (size_t) len) != (size_t) len) {
        debug("Read from key file %.200s failed: %.100s", filename,
              strerror(errno));
        buffer_free(&buffer);
        close(fd);
        return NULL;
    }

    /* Check that it is at least big enough to contain the ID string. */
    if (len < sizeof(authfile_id_string)) {
        debug3("Not a RSA1 key file %.200s.", filename);
        buffer_free(&buffer);
        close(fd);
        return NULL;
    }
    /*
     * Make sure it begins with the id string.  Consume the id string
     * from the buffer.
     */
    for (i = 0; i < sizeof(authfile_id_string); i++)
        if (buffer_get_char(&buffer) != authfile_id_string[i]) {
            debug3("Not a RSA1 key file %.200s.", filename);
            buffer_free(&buffer);
            close(fd);
            return NULL;
        }

    /* Read cipher type. */
    cipher_type = buffer_get_char(&buffer);
    (void) buffer_get_int(&buffer);	/* Reserved data. */

    /* Read the public key from the buffer. */
    (void) buffer_get_int(&buffer);
    prv = key_new_private(KEY_RSA1);

    buffer_get_bignum(&buffer, prv->rsa->n);
    buffer_get_bignum(&buffer, prv->rsa->e);
    if (commentp)
        *commentp = buffer_get_string(&buffer, NULL);
    else
        xfree(buffer_get_string(&buffer, NULL));

    /* Check that it is a supported cipher. */
    cipher = cipher_by_number(cipher_type);
    if (cipher == NULL) {
        debug("Unsupported cipher %d used in key file %.200s.",
              cipher_type, filename);
        buffer_free(&buffer);
        goto fail;
    }
    /* Initialize space for decrypted data. */
    buffer_init(&decrypted);
    cp = buffer_append_space(&decrypted, buffer_len(&buffer));

    /* Rest of the buffer is encrypted.  Decrypt it using the passphrase. */
    cipher_set_key_string(&ciphercontext, cipher, passphrase,
                          CIPHER_DECRYPT);
    cipher_crypt(&ciphercontext, cp,
                 buffer_ptr(&buffer), buffer_len(&buffer));
    cipher_cleanup(&ciphercontext);
    memset(&ciphercontext, 0, sizeof(ciphercontext));
    buffer_free(&buffer);

    check1 = buffer_get_char(&decrypted);
    check2 = buffer_get_char(&decrypted);
    if (check1 != buffer_get_char(&decrypted) ||
            check2 != buffer_get_char(&decrypted)) {
        if (strcmp(passphrase, "") != 0)
            debug("Bad passphrase supplied for key file %.200s.",
                  filename);
        /* Bad passphrase. */
        buffer_free(&decrypted);
        goto fail;
    }
    /* Read the rest of the private key. */
    buffer_get_bignum(&decrypted, prv->rsa->d);
    buffer_get_bignum(&decrypted, prv->rsa->iqmp);		/* u */
    /* in SSL and SSH v1 p and q are exchanged */
    buffer_get_bignum(&decrypted, prv->rsa->q);		/* p */
    buffer_get_bignum(&decrypted, prv->rsa->p);		/* q */

    /* calculate p-1 and q-1 */
    rsa_generate_additional_parameters(prv->rsa);

    buffer_free(&decrypted);

    /* enable blinding */
    if (RSA_blinding_on(prv->rsa, NULL) != 1) {
        error("key_load_private_rsa1: RSA_blinding_on failed");
        goto fail;
    }
    close(fd);
    return prv;

fail:
    if (commentp)
        xfree(*commentp);
    close(fd);
    key_free(prv);
    return NULL;
}