Пример #1
0
static int
sec_prot_internal(struct connectdata *conn, int level)
{
  char *p;
  unsigned int s = 1048576;
  ssize_t nread;

  if(!conn->sec_complete){
    infof(conn->data, "No security data exchange has taken place.\n");
    return -1;
  }

  if(level){
    int code;
    if(Curl_ftpsendf(conn, "PBSZ %u", s))
      return -1;

    if(Curl_GetFTPResponse(&nread, conn, &code))
      return -1;

    if(code/100 != '2'){
      failf(conn->data, "Failed to set protection buffer size.");
      return -1;
    }
    conn->buffer_size = s;

    p = strstr(conn->data->state.buffer, "PBSZ=");
    if(p)
      sscanf(p, "PBSZ=%u", &s);
    if(s < conn->buffer_size)
      conn->buffer_size = s;
  }

  if(Curl_ftpsendf(conn, "PROT %c", level["CSEP"]))
    return -1;

  if(Curl_GetFTPResponse(&nread, conn, NULL))
    return -1;

  if(conn->data->state.buffer[0] != '2'){
    failf(conn->data, "Failed to set protection level.");
    return -1;
  }
    
  conn->data_prot = (enum protection_level)level;
  return 0;
}
Пример #2
0
/* Send an FTP command defined by |message| and the optional arguments. The
   function returns the ftp_code. If an error occurs, -1 is returned. */
static int ftp_send_command(struct connectdata *conn, const char *message, ...)
{
  int ftp_code;
  ssize_t nread;
  va_list args;
  char print_buffer[50];

  va_start(args, message);
  vsnprintf(print_buffer, sizeof(print_buffer), message, args);
  va_end(args);

  if(Curl_ftpsendf(conn, print_buffer) != CURLE_OK) {
    ftp_code = -1;
  }
  else {
    if(Curl_GetFTPResponse(&nread, conn, &ftp_code) != CURLE_OK)
      ftp_code = -1;
  }

  (void)nread; /* Unused */
  return ftp_code;
}
Пример #3
0
Файл: krb5.c Проект: 0w/moai-dev
static int
krb5_auth(void *app_data, struct connectdata *conn)
{
  int ret;
  char *p;
  const char *host = conn->dns_entry->addr->ai_canonname;
  ssize_t nread;
  curl_socklen_t l = sizeof(conn->local_addr);
  struct SessionHandle *data = conn->data;
  CURLcode result;
  const char *service = "ftp", *srv_host = "host";
  gss_buffer_desc gssbuf, _gssresp, *gssresp;
  OM_uint32 maj, min;
  gss_name_t gssname;
  gss_ctx_id_t *context = app_data;
  struct gss_channel_bindings_struct chan;

  if(getsockname(conn->sock[FIRSTSOCKET],
                 (struct sockaddr *)LOCAL_ADDR, &l) < 0)
    perror("getsockname()");

  chan.initiator_addrtype = GSS_C_AF_INET;
  chan.initiator_address.length = l - 4;
  chan.initiator_address.value =
    &((struct sockaddr_in *)LOCAL_ADDR)->sin_addr.s_addr;
  chan.acceptor_addrtype = GSS_C_AF_INET;
  chan.acceptor_address.length = l - 4;
  chan.acceptor_address.value =
    &((struct sockaddr_in *)REMOTE_ADDR)->sin_addr.s_addr;
  chan.application_data.length = 0;
  chan.application_data.value = NULL;

  /* this loop will execute twice (once for service, once for host) */
  while(1) {
    /* this really shouldn't be repeated here, but can't help it */
    if(service == srv_host) {
      result = Curl_ftpsendf(conn, "AUTH GSSAPI");

      if(result)
        return -2;
      if(Curl_GetFTPResponse(&nread, conn, NULL))
        return -1;

      if(data->state.buffer[0] != '3')
        return -1;
    }

    gssbuf.value = data->state.buffer;
    gssbuf.length = snprintf(gssbuf.value, BUFSIZE, "%s@%s", service, host);
    maj = gss_import_name(&min, &gssbuf, GSS_C_NT_HOSTBASED_SERVICE, &gssname);
    if(maj != GSS_S_COMPLETE) {
      gss_release_name(&min, &gssname);
      if(service == srv_host) {
        Curl_failf(data, "Error importing service name %s", gssbuf.value);
        return AUTH_ERROR;
      }
      service = srv_host;
      continue;
    }
    {
      gss_OID t;
      gss_display_name(&min, gssname, &gssbuf, &t);
      Curl_infof(data, "Trying against %s\n", gssbuf.value);
      gss_release_buffer(&min, &gssbuf);
    }
    gssresp = GSS_C_NO_BUFFER;
    *context = GSS_C_NO_CONTEXT;

    do {
      ret = AUTH_OK;
      maj = gss_init_sec_context(&min,
                                 GSS_C_NO_CREDENTIAL,
                                 context,
                                 gssname,
                                 GSS_C_NO_OID,
                                 GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
                                 0,
                                 &chan,
                                 gssresp,
                                 NULL,
                                 &gssbuf,
                                 NULL,
                                 NULL);

      if(gssresp) {
        free(_gssresp.value);
        gssresp = NULL;
      }

      if(maj != GSS_S_COMPLETE && maj != GSS_S_CONTINUE_NEEDED) {
        Curl_infof(data, "Error creating security context");
        ret = AUTH_ERROR;
        break;
      }

      if(gssbuf.length != 0) {
        if(Curl_base64_encode(data, (char *)gssbuf.value, gssbuf.length, &p)
           < 1) {
          Curl_infof(data, "Out of memory base64-encoding");
          ret = AUTH_CONTINUE;
          break;
        }

        result = Curl_ftpsendf(conn, "ADAT %s", p);

        free(p);

        if(result) {
          ret = -2;
          break;
        }

        if(Curl_GetFTPResponse(&nread, conn, NULL)) {
          ret = -1;
          break;
        }

        if(data->state.buffer[0] != '2' && data->state.buffer[0] != '3'){
          Curl_infof(data, "Server didn't accept auth data\n");
          ret = AUTH_ERROR;
          break;
        }

        p = data->state.buffer + 4;
        p = strstr(p, "ADAT=");
        if(p) {
          _gssresp.length = Curl_base64_decode(p + 5, (unsigned char **)
                                               &_gssresp.value);
          if(_gssresp.length < 1) {
            Curl_failf(data, "Out of memory base64-encoding");
            ret = AUTH_CONTINUE;
            break;
          }
        }

        gssresp = &_gssresp;
      }
    } while(maj == GSS_S_CONTINUE_NEEDED);

    gss_release_name(&min, &gssname);

    if(gssresp)
      free(_gssresp.value);

    if(ret == AUTH_OK || service == srv_host)
      return ret;

    service = srv_host;
  }
}
Пример #4
0
int
Curl_sec_login(struct connectdata *conn)
{
  int ret;
  struct Curl_sec_client_mech **m;
  ssize_t nread;
  struct SessionHandle *data=conn->data;
  int ftpcode;

  for(m = mechs; *m && (*m)->name; m++) {
    void *tmp;

    tmp = realloc(conn->app_data, (*m)->size);
    if (tmp == NULL) {
      failf (data, "realloc %u failed", (*m)->size);
      return -1;
    }
    conn->app_data = tmp;
	    
    if((*m)->init && (*(*m)->init)(conn->app_data) != 0) {
      infof(data, "Skipping %s...\n", (*m)->name);
      continue;
    }
    infof(data, "Trying %s...\n", (*m)->name);

    if(Curl_ftpsendf(conn, "AUTH %s", (*m)->name))
      return -1;

    if(Curl_GetFTPResponse(&nread, conn, &ftpcode))
      return -1;

    if(conn->data->state.buffer[0] != '3'){
      switch(ftpcode) {
      case 504:
        infof(data,
              "%s is not supported by the server.\n", (*m)->name);
        break;
      case 534:
        infof(data, "%s rejected as security mechanism.\n", (*m)->name);
        break;
      default:
        if(conn->data->state.buffer[0] == '5') {
          infof(data, "The server doesn't support the FTP "
                "security extensions.\n");
          return -1;
        }
        break;
      }
      continue;
    }

    ret = (*(*m)->auth)(conn->app_data, conn);
	
    if(ret == AUTH_CONTINUE)
      continue;
    else if(ret != AUTH_OK){
      /* mechanism is supposed to output error string */
      return -1;
    }
    conn->mech = *m;
    conn->sec_complete = 1;
    conn->command_prot = prot_safe;
    break;
  }
    
  return *m == NULL;
}
Пример #5
0
CURLcode Curl_krb_kauth(struct connectdata *conn)
{
  des_cblock key;
  des_key_schedule schedule;
  KTEXT_ST tkt, tktcopy;
  char *name;
  char *p;
  char passwd[100];
  size_t tmp;
  ssize_t nread;
  int save;
  CURLcode result;
  unsigned char *ptr;

  save = Curl_set_command_prot(conn, prot_private);

  result = Curl_ftpsendf(conn, "SITE KAUTH %s", conn->user);

  if(result)
    return result;

  result = Curl_GetFTPResponse(&nread, conn, NULL);
  if(result)
    return result;

  if(conn->data->state.buffer[0] != '3'){
    Curl_set_command_prot(conn, save);
    return CURLE_FTP_WEIRD_SERVER_REPLY;
  }

  p = strstr(conn->data->state.buffer, "T=");
  if(!p) {
    Curl_failf(conn->data, "Bad reply from server");
    Curl_set_command_prot(conn, save);
    return CURLE_FTP_WEIRD_SERVER_REPLY;
  }

  p += 2;
  tmp = Curl_base64_decode(p, &ptr);
  if(tmp >= sizeof(tkt.dat)) {
    free(ptr);
    tmp=0;
  }
  if(!tmp || !ptr) {
    Curl_failf(conn->data, "Failed to decode base64 in reply");
    Curl_set_command_prot(conn, save);
    return CURLE_FTP_WEIRD_SERVER_REPLY;
  }
  memcpy((char *)tkt.dat, ptr, tmp);
  free(ptr);
  tkt.length = tmp;
  tktcopy.length = tkt.length;

  p = strstr(conn->data->state.buffer, "P=");
  if(!p) {
    Curl_failf(conn->data, "Bad reply from server");
    Curl_set_command_prot(conn, save);
    return CURLE_FTP_WEIRD_SERVER_REPLY;
  }
  name = p + 2;
  for(; *p && *p != ' ' && *p != '\r' && *p != '\n'; p++);
  *p = 0;

  des_string_to_key (conn->passwd, &key);
  des_key_sched(&key, schedule);

  des_pcbc_encrypt((void *)tkt.dat, (void *)tktcopy.dat,
                   tkt.length,
                   schedule, &key, DES_DECRYPT);
  if(strcmp ((char*)tktcopy.dat + 8,
              KRB_TICKET_GRANTING_TICKET) != 0) {
    afs_string_to_key(passwd,
                      krb_realmofhost(conn->host.name),
                      &key);
    des_key_sched(&key, schedule);
    des_pcbc_encrypt((void *)tkt.dat, (void *)tktcopy.dat,
                     tkt.length,
                     schedule, &key, DES_DECRYPT);
  }
  memset(key, 0, sizeof(key));
  memset(schedule, 0, sizeof(schedule));
  memset(passwd, 0, sizeof(passwd));
  if(Curl_base64_encode(conn->data, (char *)tktcopy.dat, tktcopy.length, &p)
     < 1) {
    failf(conn->data, "Out of memory base64-encoding.");
    Curl_set_command_prot(conn, save);
    return CURLE_OUT_OF_MEMORY;
  }
  memset (tktcopy.dat, 0, tktcopy.length);

  result = Curl_ftpsendf(conn, "SITE KAUTH %s %s", name, p);
  free(p);
  if(result)
    return result;

  result = Curl_GetFTPResponse(&nread, conn, NULL);
  if(result)
    return result;
  Curl_set_command_prot(conn, save);

  return CURLE_OK;
}
Пример #6
0
static int
krb4_auth(void *app_data, struct connectdata *conn)
{
  int ret;
  char *p;
  unsigned char *ptr;
  size_t len;
  KTEXT_ST adat;
  MSG_DAT msg_data;
  int checksum;
  u_int32_t cs;
  struct krb4_data *d = app_data;
  char *host = conn->host.name;
  ssize_t nread;
  int l = sizeof(conn->local_addr);
  struct SessionHandle *data = conn->data;
  CURLcode result;

  if(getsockname(conn->sock[FIRSTSOCKET],
                 (struct sockaddr *)LOCAL_ADDR, &l) < 0)
    perror("getsockname()");

  checksum = getpid();
  ret = mk_auth(d, &adat, "ftp", host, checksum);
  if(ret == KDC_PR_UNKNOWN)
    ret = mk_auth(d, &adat, "rcmd", host, checksum);
  if(ret) {
    infof(data, "%s\n", krb_get_err_text(ret));
    return AUTH_CONTINUE;
  }

#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM
  if(krb_get_config_bool("nat_in_use")) {
    struct sockaddr_in *localaddr  = (struct sockaddr_in *)LOCAL_ADDR;
    struct in_addr natAddr;

    if(krb_get_our_ip_for_realm(krb_realmofhost(host),
                                 &natAddr) != KSUCCESS
        && krb_get_our_ip_for_realm(NULL, &natAddr) != KSUCCESS)
      infof(data, "Can't get address for realm %s\n",
                 krb_realmofhost(host));
    else {
      if(natAddr.s_addr != localaddr->sin_addr.s_addr) {
        char addr_buf[128];
        if(Curl_inet_ntop(AF_INET, natAddr, addr_buf, sizeof(addr_buf)))
          infof(data, "Using NAT IP address (%s) for kerberos 4\n", addr_buf);
        localaddr->sin_addr = natAddr;
      }
    }
  }
#endif

  if(Curl_base64_encode(conn->data, (char *)adat.dat, adat.length, &p) < 1) {
    Curl_failf(data, "Out of memory base64-encoding");
    return AUTH_CONTINUE;
  }

  result = Curl_ftpsendf(conn, "ADAT %s", p);

  free(p);

  if(result)
    return -2;

  if(Curl_GetFTPResponse(&nread, conn, NULL))
    return -1;

  if(data->state.buffer[0] != '2'){
    Curl_failf(data, "Server didn't accept auth data");
    return AUTH_ERROR;
  }

  p = strstr(data->state.buffer, "ADAT=");
  if(!p) {
    Curl_failf(data, "Remote host didn't send adat reply");
    return AUTH_ERROR;
  }
  p += 5;
  len = Curl_base64_decode(p, &ptr);
  if(len > sizeof(adat.dat)-1) {
    free(ptr);
    len=0;
  }
  if(!len || !ptr) {
    Curl_failf(data, "Failed to decode base64 from server");
    return AUTH_ERROR;
  }
  memcpy((char *)adat.dat, ptr, len);
  free(ptr);
  adat.length = len;
  ret = krb_rd_safe(adat.dat, adat.length, &d->key,
                    (struct sockaddr_in *)hisctladdr,
                    (struct sockaddr_in *)myctladdr, &msg_data);
  if(ret) {
    Curl_failf(data, "Error reading reply from server: %s",
               krb_get_err_text(ret));
    return AUTH_ERROR;
  }
  krb_get_int(msg_data.app_data, &cs, 4, 0);
  if(cs - checksum != 1) {
    Curl_failf(data, "Bad checksum returned from server");
    return AUTH_ERROR;
  }
  return AUTH_OK;
}