示例#1
0
文件: pki.c 项目: codinn/libssh
int ssh_pki_import_signature_blob(const ssh_string sig_blob,
                                  const ssh_key pubkey,
                                  ssh_signature *psig)
{
    ssh_signature sig;
    enum ssh_keytypes_e type;
    ssh_string str;
    ssh_buffer buf;
    int rc;

    if (sig_blob == NULL || psig == NULL) {
        return SSH_ERROR;
    }

    buf = ssh_buffer_new();
    if (buf == NULL) {
        return SSH_ERROR;
    }

    rc = ssh_buffer_add_data(buf,
                             ssh_string_data(sig_blob),
                             ssh_string_len(sig_blob));
    if (rc < 0) {
        ssh_buffer_free(buf);
        return SSH_ERROR;
    }

    str = ssh_buffer_get_ssh_string(buf);
    if (str == NULL) {
        ssh_buffer_free(buf);
        return SSH_ERROR;
    }

    type = ssh_key_type_from_name(ssh_string_get_char(str));
    ssh_string_free(str);

    str = ssh_buffer_get_ssh_string(buf);
    ssh_buffer_free(buf);
    if (str == NULL) {
        return SSH_ERROR;
    }

    sig = pki_signature_from_blob(pubkey, str, type);
    ssh_string_free(str);
    if (sig == NULL) {
        return SSH_ERROR;
    }

    *psig = sig;
    return SSH_OK;
}
示例#2
0
文件: pki.c 项目: codinn/libssh
/**
 * @brief Import a base64 formated public key from a memory c-string.
 *
 * @param[in]  b64_key  The base64 key to format.
 *
 * @param[in]  type     The type of the key to format.
 *
 * @param[out] pkey     A pointer where the allocated key can be stored. You
 *                      need to free the memory.
 *
 * @return              SSH_OK on success, SSH_ERROR on error.
 *
 * @see ssh_key_free()
 */
int ssh_pki_import_pubkey_base64(const char *b64_key,
                                 enum ssh_keytypes_e type,
                                 ssh_key *pkey) {
    ssh_buffer buffer;
    ssh_string type_s;
    int rc;

    if (b64_key == NULL || pkey == NULL) {
        return SSH_ERROR;
    }

    buffer = base64_to_bin(b64_key);
    if (buffer == NULL) {
        return SSH_ERROR;
    }

    type_s = ssh_buffer_get_ssh_string(buffer);
    if (type_s == NULL) {
        ssh_buffer_free(buffer);
        return SSH_ERROR;
    }
    ssh_string_free(type_s);

    if (type == SSH_KEYTYPE_RSA_CERT01 ||
        type == SSH_KEYTYPE_DSS_CERT01) {
        rc = pki_import_cert_buffer(buffer, type, pkey);
    } else {
        rc = pki_import_pubkey_buffer(buffer, type, pkey);
    }
    ssh_buffer_free(buffer);

    return rc;
}
示例#3
0
文件: ecdh.c 项目: caidongyun/libssh
/** @internal
 * @brief parses a SSH_MSG_KEX_ECDH_REPLY packet and sends back
 * a SSH_MSG_NEWKEYS
 */
int ssh_client_ecdh_reply(ssh_session session, ssh_buffer packet){
  ssh_string q_s_string = NULL;
  ssh_string pubkey = NULL;
  ssh_string signature = NULL;
  int rc;
  pubkey = ssh_buffer_get_ssh_string(packet);
  if (pubkey == NULL){
    ssh_set_error(session,SSH_FATAL, "No public key in packet");
    goto error;
  }
  ecdh_import_pubkey(session, pubkey);

  q_s_string = ssh_buffer_get_ssh_string(packet);
  if (q_s_string == NULL) {
    ssh_set_error(session,SSH_FATAL, "No Q_S ECC point in packet");
    goto error;
  }
  session->next_crypto->ecdh_server_pubkey = q_s_string;
  signature = ssh_buffer_get_ssh_string(packet);
  if (signature == NULL) {
    ssh_set_error(session, SSH_FATAL, "No signature in packet");
    goto error;
  }
  session->next_crypto->dh_server_signature = signature;
  signature=NULL; /* ownership changed */
  /* TODO: verify signature now instead of waiting for NEWKEYS */
  if (ecdh_build_k(session) < 0) {
    ssh_set_error(session, SSH_FATAL, "Cannot build k number");
    goto error;
  }

  /* Send the MSG_NEWKEYS */
  if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
    goto error;
  }

  rc=ssh_packet_send(session);
  SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");
  return rc;
error:
  return SSH_ERROR;
}
示例#4
0
文件: pki.c 项目: codinn/libssh
/**
 * @internal
 *
 * @brief Import a public key from a ssh string.
 *
 * @param[in]  key_blob The key blob to import as specified in RFC 4253 section
 *                      6.6 "Public Key Algorithms".
 *
 * @param[out] pkey     A pointer where the allocated key can be stored. You
 *                      need to free the memory.
 *
 * @return              SSH_OK on success, SSH_ERROR on error.
 *
 * @see ssh_key_free()
 */
int ssh_pki_import_pubkey_blob(const ssh_string key_blob,
                               ssh_key *pkey) {
    ssh_buffer buffer;
    ssh_string type_s = NULL;
    enum ssh_keytypes_e type;
    int rc;

    if (key_blob == NULL || pkey == NULL) {
        return SSH_ERROR;
    }

    buffer = ssh_buffer_new();
    if (buffer == NULL) {
        SSH_LOG(SSH_LOG_WARN, "Out of memory!");
        return SSH_ERROR;
    }

    rc = ssh_buffer_add_data(buffer, ssh_string_data(key_blob),
            ssh_string_len(key_blob));
    if (rc < 0) {
        SSH_LOG(SSH_LOG_WARN, "Out of memory!");
        goto fail;
    }

    type_s = ssh_buffer_get_ssh_string(buffer);
    if (type_s == NULL) {
        SSH_LOG(SSH_LOG_WARN, "Out of memory!");
        goto fail;
    }

    type = ssh_key_type_from_name(ssh_string_get_char(type_s));
    if (type == SSH_KEYTYPE_UNKNOWN) {
        SSH_LOG(SSH_LOG_WARN, "Unknown key type found!");
        goto fail;
    }
    ssh_string_free(type_s);

    if (type == SSH_KEYTYPE_RSA_CERT01 ||
        type == SSH_KEYTYPE_DSS_CERT01) {
        rc = pki_import_cert_buffer(buffer, type, pkey);
    } else {
        rc = pki_import_pubkey_buffer(buffer, type, pkey);
    }

    ssh_buffer_free(buffer);

    return rc;
fail:
    ssh_buffer_free(buffer);
    ssh_string_free(type_s);

    return SSH_ERROR;
}
示例#5
0
文件: server.c 项目: Paxxi/libssh
/** @internal
 * @brief parse an incoming SSH_MSG_KEXDH_INIT packet and complete
 *        key exchange
 **/
static int ssh_server_kexdh_init(ssh_session session, ssh_buffer packet){
    ssh_string e;
    e = ssh_buffer_get_ssh_string(packet);
    if (e == NULL) {
      ssh_set_error(session, SSH_FATAL, "No e number in client request");
      return -1;
    }
    if (ssh_dh_import_e(session, e) < 0) {
      ssh_set_error(session, SSH_FATAL, "Cannot import e number");
      session->session_state=SSH_SESSION_STATE_ERROR;
    } else {
      session->dh_handshake_state=DH_STATE_INIT_SENT;
      dh_handshake_server(session);
    }
    ssh_string_free(e);
    return SSH_OK;
}
示例#6
0
/*
 * Test the behavior of ssh_buffer_get_ssh_string with invalid data
 */
static void *thread_ssh_buffer_get_ssh_string(void *threadid)
{
    ssh_buffer buffer = NULL;
    size_t i, j, k, l;
    int rc;
    /* some values that can go wrong */
    uint32_t values[] = {
        0xffffffff, 0xfffffffe, 0xfffffffc, 0xffffff00,
        0x80000000, 0x80000004, 0x7fffffff};
    char data[128] = {0};

    /* Unused */
    (void)threadid;

    memset(data, 'X', sizeof(data));

    for (i = 0; i < ARRAY_SIZE(values); ++i) {
        for (j = 0; j < (int)sizeof(data); ++j) {
            for (k = 1; k < 5; ++k) {
                buffer = ssh_buffer_new();
                assert_non_null(buffer);

                for (l = 0; l < k; ++l) {
                    rc = ssh_buffer_add_u32(buffer, htonl(values[i]));
                    assert_int_equal(rc, 0);
                }
                rc = ssh_buffer_add_data(buffer,data,j);
                assert_int_equal(rc, 0);
                for (l = 0; l < k; ++l) {
                    ssh_string str = ssh_buffer_get_ssh_string(buffer);
                    assert_null(str);
                    SSH_STRING_FREE(str);
                }
                SSH_BUFFER_FREE(buffer);
            }
        }
    }

    pthread_exit(NULL);
}
示例#7
0
文件: pki.c 项目: codinn/libssh
static int pki_import_pubkey_buffer(ssh_buffer buffer,
                                    enum ssh_keytypes_e type,
                                    ssh_key *pkey) {
    ssh_key key;
    int rc;

    key = ssh_key_new();
    if (key == NULL) {
        return SSH_ERROR;
    }

    key->type = type;
    key->type_c = ssh_key_type_to_char(type);
    key->flags = SSH_KEY_FLAG_PUBLIC;

    switch (type) {
        case SSH_KEYTYPE_DSS:
            {
                ssh_string p;
                ssh_string q;
                ssh_string g;
                ssh_string pubkey;

                p = ssh_buffer_get_ssh_string(buffer);
                if (p == NULL) {
                    goto fail;
                }
                q = ssh_buffer_get_ssh_string(buffer);
                if (q == NULL) {
                    ssh_string_burn(p);
                    ssh_string_free(p);

                    goto fail;
                }
                g = ssh_buffer_get_ssh_string(buffer);
                if (g == NULL) {
                    ssh_string_burn(p);
                    ssh_string_free(p);
                    ssh_string_burn(q);
                    ssh_string_free(q);

                    goto fail;
                }
                pubkey = ssh_buffer_get_ssh_string(buffer);
                if (pubkey == NULL) {
                    ssh_string_burn(p);
                    ssh_string_free(p);
                    ssh_string_burn(q);
                    ssh_string_free(q);
                    ssh_string_burn(g);
                    ssh_string_free(g);

                    goto fail;
                }

                rc = pki_pubkey_build_dss(key, p, q, g, pubkey);
#ifdef DEBUG_CRYPTO
                ssh_print_hexa("p", ssh_string_data(p), ssh_string_len(p));
                ssh_print_hexa("q", ssh_string_data(q), ssh_string_len(q));
                ssh_print_hexa("g", ssh_string_data(g), ssh_string_len(g));
#endif
                ssh_string_burn(p);
                ssh_string_free(p);
                ssh_string_burn(q);
                ssh_string_free(q);
                ssh_string_burn(g);
                ssh_string_free(g);
                ssh_string_burn(pubkey);
                ssh_string_free(pubkey);
                if (rc == SSH_ERROR) {
                    goto fail;
                }
            }
            break;
        case SSH_KEYTYPE_RSA:
        case SSH_KEYTYPE_RSA1:
            {
                ssh_string e;
                ssh_string n;

                e = ssh_buffer_get_ssh_string(buffer);
                if (e == NULL) {
                    goto fail;
                }
                n = ssh_buffer_get_ssh_string(buffer);
                if (n == NULL) {
                    ssh_string_burn(e);
                    ssh_string_free(e);

                    goto fail;
                }

                rc = pki_pubkey_build_rsa(key, e, n);
#ifdef DEBUG_CRYPTO
                ssh_print_hexa("e", ssh_string_data(e), ssh_string_len(e));
                ssh_print_hexa("n", ssh_string_data(n), ssh_string_len(n));
#endif
                ssh_string_burn(e);
                ssh_string_free(e);
                ssh_string_burn(n);
                ssh_string_free(n);
                if (rc == SSH_ERROR) {
                    goto fail;
                }
            }
            break;
        case SSH_KEYTYPE_ECDSA:
#ifdef HAVE_ECC
            {
                ssh_string e;
                ssh_string i;
                int nid;

                i = ssh_buffer_get_ssh_string(buffer);
                if (i == NULL) {
                    goto fail;
                }
                nid = pki_key_ecdsa_nid_from_name(ssh_string_get_char(i));
                ssh_string_free(i);
                if (nid == -1) {
                    goto fail;
                }


                e = ssh_buffer_get_ssh_string(buffer);
                if (e == NULL) {
                    goto fail;
                }

                rc = pki_pubkey_build_ecdsa(key, nid, e);
                ssh_string_burn(e);
                ssh_string_free(e);
                if (rc < 0) {
                    goto fail;
                }

                /* Update key type */
                key->type_c = ssh_pki_key_ecdsa_name(key);
            }
            break;
#endif
        case SSH_KEYTYPE_ED25519:
        {
            ssh_string pubkey = ssh_buffer_get_ssh_string(buffer);
            if (ssh_string_len(pubkey) != ED25519_PK_LEN) {
                SSH_LOG(SSH_LOG_WARN, "Invalid public key length");
                ssh_string_burn(pubkey);
                ssh_string_free(pubkey);
                goto fail;
            }

            key->ed25519_pubkey = malloc(ED25519_PK_LEN);
            if (key->ed25519_pubkey == NULL) {
                ssh_string_burn(pubkey);
                ssh_string_free(pubkey);
                goto fail;
            }

            memcpy(key->ed25519_pubkey, ssh_string_data(pubkey), ED25519_PK_LEN);
            ssh_string_burn(pubkey);
            ssh_string_free(pubkey);
        }
        break;
        case SSH_KEYTYPE_DSS_CERT01:
        case SSH_KEYTYPE_RSA_CERT01:
        case SSH_KEYTYPE_UNKNOWN:
        default:
            SSH_LOG(SSH_LOG_WARN, "Unknown public key protocol %d", type);
            goto fail;
    }

    *pkey = key;
    return SSH_OK;
fail:
    ssh_key_free(key);

    return SSH_ERROR;
}
示例#8
0
文件: ecdh.c 项目: caidongyun/libssh
int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet){
    /* ECDH keys */
    ssh_string q_c_string;
    ssh_string q_s_string;
    EC_KEY *ecdh_key;
    const EC_GROUP *group;
    const EC_POINT *ecdh_pubkey;
    bignum_CTX ctx;
    /* SSH host keys (rsa,dsa,ecdsa) */
    ssh_key privkey;
    ssh_string sig_blob = NULL;
    int len;
    int rc;

    /* Extract the client pubkey from the init packet */
    q_c_string = ssh_buffer_get_ssh_string(packet);
    if (q_c_string == NULL) {
        ssh_set_error(session,SSH_FATAL, "No Q_C ECC point in packet");
        return SSH_ERROR;
    }
    session->next_crypto->ecdh_client_pubkey = q_c_string;

    /* Build server's keypair */

    ctx = BN_CTX_new();
    ecdh_key = EC_KEY_new_by_curve_name(NISTP256);
    if (ecdh_key == NULL) {
        ssh_set_error_oom(session);
        BN_CTX_free(ctx);
        return SSH_ERROR;
    }

    group = EC_KEY_get0_group(ecdh_key);
    EC_KEY_generate_key(ecdh_key);

    ecdh_pubkey = EC_KEY_get0_public_key(ecdh_key);
    len = EC_POINT_point2oct(group,
                             ecdh_pubkey,
                             POINT_CONVERSION_UNCOMPRESSED,
                             NULL,
                             0,
                             ctx);

    q_s_string = ssh_string_new(len);
    if (q_s_string == NULL) {
        EC_KEY_free(ecdh_key);
        BN_CTX_free(ctx);
        return SSH_ERROR;
    }

    EC_POINT_point2oct(group,
                       ecdh_pubkey,
                       POINT_CONVERSION_UNCOMPRESSED,
                       ssh_string_data(q_s_string),
                       len,
                       ctx);
    BN_CTX_free(ctx);

    session->next_crypto->ecdh_privkey = ecdh_key;
    session->next_crypto->ecdh_server_pubkey = q_s_string;

    /* build k and session_id */
    rc = ecdh_build_k(session);
    if (rc < 0) {
        ssh_set_error(session, SSH_FATAL, "Cannot build k number");
        return SSH_ERROR;
    }

    /* privkey is not allocated */
    rc = ssh_get_key_params(session, &privkey);
    if (rc == SSH_ERROR) {
        return SSH_ERROR;
    }

    rc = ssh_make_sessionid(session);
    if (rc != SSH_OK) {
        ssh_set_error(session, SSH_FATAL, "Could not create a session id");
        return SSH_ERROR;
    }

    sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
    if (sig_blob == NULL) {
        ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
        return SSH_ERROR;
    }

    rc = ssh_buffer_pack(session->out_buffer,
                         "bSSS",
                         SSH2_MSG_KEXDH_REPLY,
                         session->next_crypto->server_pubkey, /* host's pubkey */
                         q_s_string, /* ecdh public key */
                         sig_blob); /* signature blob */

    ssh_string_free(sig_blob);

    if (rc != SSH_OK) {
        ssh_set_error_oom(session);
        return SSH_ERROR;
    }

    SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEXDH_REPLY sent");
    rc = ssh_packet_send(session);
    if (rc == SSH_ERROR) {
        return SSH_ERROR;
    }

    /* Send the MSG_NEWKEYS */
    rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS);
    if (rc < 0) {
        return SSH_ERROR;;
    }

    session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
    rc = ssh_packet_send(session);
    SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");

    return rc;
}
示例#9
0
文件: sftpserver.c 项目: Paxxi/libssh
sftp_client_message sftp_get_client_message(sftp_session sftp) {
  ssh_session session = sftp->session;
  sftp_packet packet;
  sftp_client_message msg;
  ssh_buffer payload;
  int rc;

  msg = malloc(sizeof (struct sftp_client_message_struct));
  if (msg == NULL) {
    ssh_set_error_oom(session);
    return NULL;
  }
  ZERO_STRUCTP(msg);

  packet = sftp_packet_read(sftp);
  if (packet == NULL) {
    ssh_set_error_oom(session);
    sftp_client_message_free(msg);
    return NULL;
  }

  payload = packet->payload;
  msg->type = packet->type;
  msg->sftp = sftp;

  /* take a copy of the whole packet */
  msg->complete_message = ssh_buffer_new();
  ssh_buffer_add_data(msg->complete_message,
                      ssh_buffer_get(payload),
                      ssh_buffer_get_len(payload));

  ssh_buffer_get_u32(payload, &msg->id);

  switch(msg->type) {
    case SSH_FXP_CLOSE:
    case SSH_FXP_READDIR:
      msg->handle = ssh_buffer_get_ssh_string(payload);
      if (msg->handle == NULL) {
        ssh_set_error_oom(session);
        sftp_client_message_free(msg);
        return NULL;
      }
      break;
    case SSH_FXP_READ:
      rc = ssh_buffer_unpack(payload,
                             "Sqd",
                             &msg->handle,
                             &msg->offset,
                             &msg->len);
      if (rc != SSH_OK) {
        ssh_set_error_oom(session);
        sftp_client_message_free(msg);
        return NULL;
      }
      break;
    case SSH_FXP_WRITE:
      rc = ssh_buffer_unpack(payload,
                             "SqS",
                             &msg->handle,
                             &msg->offset,
                             &msg->data);
      if (rc != SSH_OK) {
        ssh_set_error_oom(session);
        sftp_client_message_free(msg);
        return NULL;
      }
      break;
    case SSH_FXP_REMOVE:
    case SSH_FXP_RMDIR:
    case SSH_FXP_OPENDIR:
    case SSH_FXP_READLINK:
    case SSH_FXP_REALPATH:
      rc = ssh_buffer_unpack(payload,
                             "s",
                             &msg->filename);
      if (rc != SSH_OK) {
        ssh_set_error_oom(session);
        sftp_client_message_free(msg);
        return NULL;
      }
      break;
    case SSH_FXP_RENAME:
    case SSH_FXP_SYMLINK:
      rc = ssh_buffer_unpack(payload,
                             "sS",
                             &msg->filename,
                             &msg->data);
      if (rc != SSH_OK) {
        ssh_set_error_oom(session);
        sftp_client_message_free(msg);
        return NULL;
      }
      break;
    case SSH_FXP_MKDIR:
    case SSH_FXP_SETSTAT:
      rc = ssh_buffer_unpack(payload,
                             "s",
                             &msg->filename);
      if (rc != SSH_OK) {
        ssh_set_error_oom(session);
        sftp_client_message_free(msg);
        return NULL;
      }
      msg->attr = sftp_parse_attr(sftp, payload, 0);
      if (msg->attr == NULL) {
        ssh_set_error_oom(session);
        sftp_client_message_free(msg);
        return NULL;
      }
      break;
    case SSH_FXP_FSETSTAT:
      msg->handle = ssh_buffer_get_ssh_string(payload);
      if (msg->handle == NULL) {
        ssh_set_error_oom(session);
        sftp_client_message_free(msg);
        return NULL;
      }
      msg->attr = sftp_parse_attr(sftp, payload, 0);
      if (msg->attr == NULL) {
        ssh_set_error_oom(session);
        sftp_client_message_free(msg);
        return NULL;
      }
      break;
    case SSH_FXP_LSTAT:
    case SSH_FXP_STAT:
      rc = ssh_buffer_unpack(payload,
                             "s",
                             &msg->filename);
      if (rc != SSH_OK) {
        ssh_set_error_oom(session);
        sftp_client_message_free(msg);
        return NULL;
      }
      if(sftp->version > 3) {
        ssh_buffer_unpack(payload, "d", &msg->flags);
      }
      break;
    case SSH_FXP_OPEN:
      rc = ssh_buffer_unpack(payload,
                             "sd",
                             &msg->filename,
                             &msg->flags);
      if (rc != SSH_OK) {
        ssh_set_error_oom(session);
        sftp_client_message_free(msg);
        return NULL;
      }
      msg->attr = sftp_parse_attr(sftp, payload, 0);
      if (msg->attr == NULL) {
        ssh_set_error_oom(session);
        sftp_client_message_free(msg);
        return NULL;
      }
      break;
    case SSH_FXP_FSTAT:
      rc = ssh_buffer_unpack(payload,
                             "S",
                             &msg->handle);
      if (rc != SSH_OK) {
        ssh_set_error_oom(session);
        sftp_client_message_free(msg);
        return NULL;
      }
      break;
    default:
      ssh_set_error(sftp->session, SSH_FATAL,
                    "Received unhandled sftp message %d", msg->type);
      sftp_client_message_free(msg);
      return NULL;
  }

  sftp_packet_free(packet);

  return msg;
}