cURL / Mailing Lists / curl-library / Single Mail

curl-library

RE: introduced an auth callback

From: Joe Mason <jmason_at_rim.com>
Date: Sun, 8 Jul 2012 19:04:27 +0000

Ok, back to work on the auth callback. I've put my latest code up at "https://github.com/JoeNotCharles/curl/tree/authcallback_api3" (the branch number was bumped since I rebased on the latest curl).

To recap, the current interface is:

/* Type of a parameter that will hold one or more CURLAUTH_ values */
typedef long curl_auth_scheme;

typedef enum {
  CURLAUTH_TYPE_NONE = 0, /* No authentication needed */
  CURLAUTH_TYPE_HOST = 1, /* The destination host requested authentication */
  CURLAUTH_TYPE_PROXY = 2 /* the proxy requested authentication */
} curl_auth_type;

/* Result of a curl_auth_callback */
typedef enum {
  CURLAUTHE_OK, /* send an auth reply */
  CURLAUTHE_CANCEL, /* do not send an auth reply */
  CURLAUTHE_UNKNOWN, /* an unspecified error occurred in the callback */
  CURLAUTHE_OUT_OF_MEMORY, /* the callback ran out of memory */
  CURLAUTHE_LAST /* not for use, only a marker for last-in-list */
} curlautherr;

struct curl_auth_info {
  curl_auth_type type; /* host or proxy auth */
  curl_auth_scheme scheme; /* chosen scheme */
  char *url; /* url that requires auth */
  char *realm; /* realm parsed from auth header (NULL for some schemes) */
  int succeeded; /* 1 if auth was successful, 0 if it failed */
  unsigned retry_count; /* number of failed attempts */
  char *username; /* contains last username tried or NULL */
  char *password; /* contains last password tried or NULL */
};

typedef curlautherr (*curl_auth_callback)(CURL *handle, struct curl_auth_info *info, void *userdata);

CURL_EXTERN CURLcode curl_cb_set_credentials(CURL *handle, curl_auth_type type, const char *username, const char *password);
CURL_EXTERN CURLcode curl_cb_clear_credentials(CURL *handle, curl_auth_type type);

And the callback is set with curl_easy_setopt(handle, HTTP_AUTH_FUNCTION, &func).

The callback will be called with "succeeded = false" if authentication is needed and either no username and password are set, or the current username and password were tried and failed. The client is expected to do any actions required to find a new username and password (such as querying an external tool or prompting the user) and then update them by calling the new "curl_cb_set_credentials" function.

 (And on my todo list is to have it called one final time with "succeeded = true" when authentication succeeds, just to notify the client - they might was to save the credentials now that they're known to be good, for instance.)

Question 1: Currently my code handles this callback for HTTP and HTTP proxies. We've talked about extending this to other protocols (FTP, SMTP, SOCKS proxies,etc). I won't have time to do that, but I want to be sure the interface is extensible enough that they can be easily added in the future.

Which means the name "HTTP_AUTH_FUNCTION" isn't great. Should I rename it to "AUTH_FUNCTION", so that future protocols will be handled by the same function, and the client is expected to keep track of what protocol the handle is actually using if they want to handle it differently? (For example they may need to check a different database for email passwords for SMTP than for HTTP passwords.) Or, if we add FTP and SMTP auth, should we add "FTP_AUTH_FUNCTION" and "SMTP_AUTH_FUNCTION"?

Related, should we add a third type beside curl_auth_type and curl_auth_scheme reporting the protocol in use for this handle (HTTP, FTP, SMTP, etc)? This isn't strictly necessary as the user set that protocol on the handle in the first place, but would mean less bookkeeping for them.

If we use AUTH_FUNCTION and a protocol parameter, then clients who don't care about the protocol and do the same thing for all callbacks (eg. prompt the user) will just ignore the parameter. And clients that expect to handle different protocols differently can easily switch on the parameter once curl supports it. However, clients that only want to handle HTTP auth will need to check that the protocol is HTTP and return if not; otherwise when they upgrade to a hypothetical future curl version that implements SMTP auth their auth callback will start being called for SMTP as well. I can see this leading to confusion.

On the other hand, if we use HTTP_AUTH_FUNCTION, etc, then when we upgrade curl to a version that supports SMTP auth, clients that want to support it will need to add an SMTP_AUTH_FUNCTION, so existing programs won't break. That's good. Clients that want to handle all protocols in the same way can set HTTP_AUTH_FUNCTION, SMTP_AUTH_FUNCTION, etc, to point to the same callback. (There's no need for a protocol parameter here since the client can tell what protocol is in use by which function is called.) I prefer this option as it gives the most flexibility and doesn't risk breaking clients on upgrade. But it does mean that the list of options will be expanded (which is why we already collapsed HTTP_AUTH_FUNCTION and PROXY_AUTH_FUNCTION into one).

What do you think?

Joe
---------------------------------------------------------------------
This transmission (including any attachments) may contain confidential information, privileged material (including material protected by the solicitor-client or other applicable privileges), or constitute non-public information. Any use of this information by anyone other than the intended recipient is prohibited. If you have received this transmission in error, please immediately reply to the sender and delete this information from your system. Use, dissemination, distribution, or reproduction of this transmission by unintended recipients is not authorized and may be unlawful.

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2012-07-08