Commit 59cf93cc authored by Quinn Slack's avatar Quinn Slack Committed by Daniel Stenberg
Browse files

TLS-SRP: support added when using GnuTLS

parent 4f13340a
Loading
Loading
Loading
Loading
+42 −0
Original line number Original line Diff line number Diff line
@@ -146,6 +146,7 @@ dnl initialize all the info variables
   curl_krb4_msg="no      (--with-krb4*)"
   curl_krb4_msg="no      (--with-krb4*)"
    curl_gss_msg="no      (--with-gssapi)"
    curl_gss_msg="no      (--with-gssapi)"
 curl_spnego_msg="no      (--with-spnego)"
 curl_spnego_msg="no      (--with-spnego)"
curl_tls_srp_msg="no      (--enable-tls-srp)"
    curl_res_msg="default (--enable-ares / --enable-threaded-resolver)"
    curl_res_msg="default (--enable-ares / --enable-threaded-resolver)"
   curl_ipv6_msg="no      (--enable-ipv6)"
   curl_ipv6_msg="no      (--enable-ipv6)"
    curl_idn_msg="no      (--with-libidn)"
    curl_idn_msg="no      (--with-libidn)"
@@ -1754,6 +1755,17 @@ if test "$GNUTLS_ENABLED" = "1"; then
    ])
    ])
fi
fi


dnl ---
dnl We require GnuTLS with SRP support.
dnl ---
if test "$GNUTLS_ENABLED" = "1"; then
  AC_CHECK_LIB(gnutls, gnutls_srp_verifier,
   [
     AC_DEFINE(HAVE_GNUTLS_SRP, 1, [if you have the function gnutls_srp_verifier])
     AC_SUBST(HAVE_GNUTLS_SRP, [1])
   ])
fi

dnl ----------------------------------------------------
dnl ----------------------------------------------------
dnl check for PolarSSL
dnl check for PolarSSL
dnl ----------------------------------------------------
dnl ----------------------------------------------------
@@ -2654,6 +2666,32 @@ AC_HELP_STRING([--disable-crypto-auth],[Disable cryptographic authentication]),
       AC_MSG_RESULT(yes)
       AC_MSG_RESULT(yes)
)
)


dnl ************************************************************
dnl disable TLS-SRP authentication
dnl
AC_MSG_CHECKING([whether to enable TLS-SRP authentication])
AC_ARG_ENABLE(tls-srp,
AC_HELP_STRING([--enable-tls-srp],[Enable TLS-SRP authentication])
AC_HELP_STRING([--disable-tls-srp],[Disable TLS-SRP authentication]),
[ case "$enableval" in
  no)
       AC_MSG_RESULT(no)
       AC_DEFINE(CURL_DISABLE_TLS_SRP, 1, [to disable TLS-SRP authentication])
       want_tls_srp=no
       ;;
  *)   AC_MSG_RESULT(yes)
       want_tls_srp=yes
       ;;
  esac ],
       AC_MSG_RESULT(yes)
       want_tls_srp=yes
)

if test "$want_tls_srp" = "yes" && test "x$HAVE_GNUTLS_SRP" = "x1"; then
   AC_DEFINE(USE_TLS_SRP, 1, [Use TLS-SRP authentication])
   curl_tls_srp_msg="enabled"
fi

dnl ************************************************************
dnl ************************************************************
dnl disable cookies support
dnl disable cookies support
dnl
dnl
@@ -2802,6 +2840,9 @@ if test "x$USE_SSLEAY" = "x1" -o "x$USE_WINDOWS_SSPI" = "x1" \
    -o "x$GNUTLS_ENABLED" = "x1" -o "x$NSS_ENABLED" = "x1"; then
    -o "x$GNUTLS_ENABLED" = "x1" -o "x$NSS_ENABLED" = "x1"; then
  SUPPORT_FEATURES="$SUPPORT_FEATURES NTLM"
  SUPPORT_FEATURES="$SUPPORT_FEATURES NTLM"
fi
fi
if test "x$USE_TLS_SRP" = "x1"; then
  SUPPORT_FEATURES="$SUPPORT_FEATURES TLS-SRP"
fi


AC_SUBST(SUPPORT_FEATURES)
AC_SUBST(SUPPORT_FEATURES)


@@ -2945,6 +2986,7 @@ AC_MSG_NOTICE([Configured to build curl/libcurl:
  krb4 support:    ${curl_krb4_msg}
  krb4 support:    ${curl_krb4_msg}
  GSSAPI support:  ${curl_gss_msg}
  GSSAPI support:  ${curl_gss_msg}
  SPNEGO support:  ${curl_spnego_msg}
  SPNEGO support:  ${curl_spnego_msg}
  TLS-SRP support: ${curl_tls_srp_msg}
  resolver:        ${curl_res_msg}
  resolver:        ${curl_res_msg}
  ipv6 support:    ${curl_ipv6_msg}
  ipv6 support:    ${curl_ipv6_msg}
  IDN support:     ${curl_idn_msg}
  IDN support:     ${curl_idn_msg}
+17 −0
Original line number Original line Diff line number Diff line
@@ -502,6 +502,7 @@ typedef enum {
  CURLE_RTSP_SESSION_ERROR,      /* 86 - mismatch of RTSP Session Identifiers */
  CURLE_RTSP_SESSION_ERROR,      /* 86 - mismatch of RTSP Session Identifiers */
  CURLE_FTP_BAD_FILE_LIST,       /* 87 - unable to parse FTP file list */
  CURLE_FTP_BAD_FILE_LIST,       /* 87 - unable to parse FTP file list */
  CURLE_CHUNK_FAILED,            /* 88 - chunk callback reported error */
  CURLE_CHUNK_FAILED,            /* 88 - chunk callback reported error */
  CURLE_TLSAUTH_FAILED,          /* 89 - Failed TLS authentication */


  CURL_LAST /* never use! */
  CURL_LAST /* never use! */
} CURLcode;
} CURLcode;
@@ -1442,6 +1443,15 @@ typedef enum {
  /* send linked-list of name:port:address sets */
  /* send linked-list of name:port:address sets */
  CINIT(RESOLVE, OBJECTPOINT, 203),
  CINIT(RESOLVE, OBJECTPOINT, 203),


  /* Set a username for authenticated TLS */
  CINIT(TLSAUTH_USERNAME, OBJECTPOINT, 204),

  /* Set a password for authenticated TLS */
  CINIT(TLSAUTH_PASSWORD, OBJECTPOINT, 205),

  /* Set authentication type for authenticated TLS */
  CINIT(TLSAUTH_TYPE, OBJECTPOINT, 206),

  CURLOPT_LASTENTRY /* the last unused */
  CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
} CURLoption;


@@ -1538,6 +1548,12 @@ enum {
  CURL_SSLVERSION_LAST /* never use, keep last */
  CURL_SSLVERSION_LAST /* never use, keep last */
};
};


enum CURL_TLSAUTH {
  CURL_TLSAUTH_NONE,
  CURL_TLSAUTH_SRP,
  CURL_TLSAUTH_LAST /* never use, keep last */
};

/* symbols to use with CURLOPT_POSTREDIR.
/* symbols to use with CURLOPT_POSTREDIR.
   CURL_REDIR_POST_301 and CURL_REDIR_POST_302 can be bitwise ORed so that
   CURL_REDIR_POST_301 and CURL_REDIR_POST_302 can be bitwise ORed so that
   CURL_REDIR_POST_301 | CURL_REDIR_POST_302 == CURL_REDIR_POST_ALL */
   CURL_REDIR_POST_301 | CURL_REDIR_POST_302 == CURL_REDIR_POST_ALL */
@@ -2043,6 +2059,7 @@ typedef struct {
#define CURL_VERSION_SSPI      (1<<11) /* SSPI is supported */
#define CURL_VERSION_SSPI      (1<<11) /* SSPI is supported */
#define CURL_VERSION_CONV      (1<<12) /* character conversions supported */
#define CURL_VERSION_CONV      (1<<12) /* character conversions supported */
#define CURL_VERSION_CURLDEBUG (1<<13) /* debug memory tracking supported */
#define CURL_VERSION_CURLDEBUG (1<<13) /* debug memory tracking supported */
#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */


/*
/*
 * NAME curl_version_info()
 * NAME curl_version_info()
+66 −5
Original line number Original line Diff line number Diff line
@@ -346,6 +346,29 @@ gtls_connect_step1(struct connectdata *conn,
    return CURLE_SSL_CONNECT_ERROR;
    return CURLE_SSL_CONNECT_ERROR;
  }
  }


#ifdef USE_TLS_SRP
  if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
    infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username);

    rc = gnutls_srp_allocate_client_credentials(
           &conn->ssl[sockindex].srp_client_cred);
    if(rc != GNUTLS_E_SUCCESS) {
      failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
            gnutls_strerror(rc));
      return CURLE_TLSAUTH_FAILED;
    }

    rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex].srp_client_cred,
                                           data->set.ssl.username,
                                           data->set.ssl.password);
    if(rc != GNUTLS_E_SUCCESS) {
      failf(data, "gnutls_srp_set_client_cred() failed: %s",
            gnutls_strerror(rc));
      return CURLE_TLSAUTH_FAILED;
    }
  }
#endif

  if(data->set.ssl.CAfile) {
  if(data->set.ssl.CAfile) {
    /* set the trusted CA cert bundle file */
    /* set the trusted CA cert bundle file */
    gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
    gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
@@ -431,7 +454,16 @@ gtls_connect_step1(struct connectdata *conn,
    }
    }
  }
  }


#ifdef USE_TLS_SRP
  /* put the credentials to the current session */
  /* put the credentials to the current session */
  if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
    rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
                                conn->ssl[sockindex].srp_client_cred);
    if (rc != GNUTLS_E_SUCCESS) {
      failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
    }
  } else
#endif
    rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
    rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
                                conn->ssl[sockindex].cred);
                                conn->ssl[sockindex].cred);


@@ -496,8 +528,21 @@ gtls_connect_step3(struct connectdata *conn,
    if(data->set.ssl.verifypeer ||
    if(data->set.ssl.verifypeer ||
       data->set.ssl.verifyhost ||
       data->set.ssl.verifyhost ||
       data->set.ssl.issuercert) {
       data->set.ssl.issuercert) {
#ifdef USE_TLS_SRP
      if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
         && data->set.ssl.username != NULL
         && !data->set.ssl.verifypeer
         && gnutls_cipher_get(session)) {
        /* no peer cert, but auth is ok if we have SRP user and cipher and no
           peer verify */
      }
      else {
#endif
        failf(data, "failed to get server cert");
        failf(data, "failed to get server cert");
        return CURLE_PEER_FAILED_VERIFICATION;
        return CURLE_PEER_FAILED_VERIFICATION;
#ifdef USE_TLS_SRP
      }
#endif
    }
    }
    infof(data, "\t common name: WARNING couldn't obtain\n");
    infof(data, "\t common name: WARNING couldn't obtain\n");
  }
  }
@@ -530,8 +575,10 @@ gtls_connect_step3(struct connectdata *conn,
    else
    else
      infof(data, "\t server certificate verification OK\n");
      infof(data, "\t server certificate verification OK\n");
  }
  }
  else
  else {
    infof(data, "\t server certificate verification SKIPPED\n");
    infof(data, "\t server certificate verification SKIPPED\n");
    goto after_server_cert_verification;
  }


  /* initialize an X.509 certificate structure. */
  /* initialize an X.509 certificate structure. */
  gnutls_x509_crt_init(&x509_cert);
  gnutls_x509_crt_init(&x509_cert);
@@ -661,6 +708,8 @@ gtls_connect_step3(struct connectdata *conn,


  gnutls_x509_crt_deinit(x509_cert);
  gnutls_x509_crt_deinit(x509_cert);


after_server_cert_verification:

  /* compression algorithm (if any) */
  /* compression algorithm (if any) */
  ptr = gnutls_compression_get_name(gnutls_compression_get(session));
  ptr = gnutls_compression_get_name(gnutls_compression_get(session));
  /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
  /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
@@ -820,6 +869,12 @@ static void close_one(struct connectdata *conn,
    gnutls_certificate_free_credentials(conn->ssl[idx].cred);
    gnutls_certificate_free_credentials(conn->ssl[idx].cred);
    conn->ssl[idx].cred = NULL;
    conn->ssl[idx].cred = NULL;
  }
  }
#ifdef USE_TLS_SRP
  if (conn->ssl[idx].srp_client_cred) {
    gnutls_srp_free_client_credentials(conn->ssl[idx].srp_client_cred);
    conn->ssl[idx].srp_client_cred = NULL;
  }
#endif
}
}


void Curl_gtls_close(struct connectdata *conn, int sockindex)
void Curl_gtls_close(struct connectdata *conn, int sockindex)
@@ -889,6 +944,12 @@ int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
  }
  }
  gnutls_certificate_free_credentials(conn->ssl[sockindex].cred);
  gnutls_certificate_free_credentials(conn->ssl[sockindex].cred);


#ifdef USE_TLS_SRP
  if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
     && data->set.ssl.username != NULL)
    gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred);
#endif

  conn->ssl[sockindex].cred = NULL;
  conn->ssl[sockindex].cred = NULL;
  conn->ssl[sockindex].session = NULL;
  conn->ssl[sockindex].session = NULL;


+4 −1
Original line number Original line Diff line number Diff line
@@ -5,7 +5,7 @@
 *                            | (__| |_| |  _ <| |___
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *                             \___|\___/|_| \_\_____|
 *
 *
 * Copyright (C) 2004 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 2004 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 *
 * This software is licensed as described in the file COPYING, which
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
 * you should have received as part of this distribution. The terms
@@ -281,6 +281,9 @@ curl_easy_strerror(CURLcode error)
  case CURLE_CHUNK_FAILED:
  case CURLE_CHUNK_FAILED:
    return "Chunk callback failed";
    return "Chunk callback failed";


  case CURLE_TLSAUTH_FAILED:
    return "TLS Authentication failed";

    /* error codes not used by current libcurl */
    /* error codes not used by current libcurl */
  case CURLE_OBSOLETE4:
  case CURLE_OBSOLETE4:
  case CURLE_OBSOLETE10:
  case CURLE_OBSOLETE10:
+27 −0
Original line number Original line Diff line number Diff line
@@ -751,6 +751,9 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
   */
   */
  set->ssl.verifypeer = TRUE;
  set->ssl.verifypeer = TRUE;
  set->ssl.verifyhost = 2;
  set->ssl.verifyhost = 2;
#ifdef USE_TLS_SRP
  set->ssl.authtype = CURL_TLSAUTH_NONE;
#endif
  set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
  set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
                                                      type */
                                                      type */
  set->ssl.sessionid = TRUE; /* session ID caching enabled by default */
  set->ssl.sessionid = TRUE; /* session ID caching enabled by default */
@@ -2526,6 +2529,26 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
  case CURLOPT_FNMATCH_DATA:
  case CURLOPT_FNMATCH_DATA:
    data->set.fnmatch_data = va_arg(param, void *);
    data->set.fnmatch_data = va_arg(param, void *);
    break;
    break;
#ifdef USE_TLS_SRP
  case CURLOPT_TLSAUTH_USERNAME:
    result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME],
                       va_arg(param, char *));
    if (data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
      data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
    break;
  case CURLOPT_TLSAUTH_PASSWORD:
    result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD],
                       va_arg(param, char *));
    if (data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
      data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
    break;
  case CURLOPT_TLSAUTH_TYPE:
    if (strncmp((char *)va_arg(param, char *), "SRP", strlen("SRP")) == 0)
      data->set.ssl.authtype = CURL_TLSAUTH_SRP;
    else
      data->set.ssl.authtype = CURL_TLSAUTH_NONE;
    break;
#endif
  default:
  default:
    /* unknown tag and its companion, just ignore: */
    /* unknown tag and its companion, just ignore: */
    result = CURLE_FAILED_INIT; /* correct this */
    result = CURLE_FAILED_INIT; /* correct this */
@@ -4929,6 +4952,10 @@ static CURLcode create_conn(struct SessionHandle *data,
  data->set.ssl.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
  data->set.ssl.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
  data->set.ssl.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
  data->set.ssl.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
  data->set.ssl.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST];
  data->set.ssl.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST];
#ifdef USE_TLS_SRP
  data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME];
  data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD];
#endif


  if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config))
  if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config))
    return CURLE_OUT_OF_MEMORY;
    return CURLE_OUT_OF_MEMORY;
Loading