I am trying to login to betfair via the betfair api using curl. I have already succeeded in doing this via the command line version of curl from a bash script but I now want to do this from my C++ code directly with libcurl. Sadly libcurl is not supported by betfair so there is no direct documentation - but if command line curl works then it should all be doable.
My libcurl is failing straight away during an attempt to login (which should get a "session token" as a response). I tell curl about my certificate and key with the lines:
curl_easy_setopt(curl, CURLOPT_SSLCERT,"client-2048.crt");
curl_easy_setopt(curl, CURLOPT_SSLKEY,"client-2048.key");
Later on I call curl_easy_perform(curl);
I get a response of:
{"loginStatus":"CERT_AUTH_REQUIRED"}
According to betfair documentation this means: "Certificate required or certificate present but could not authenticate with it"
So I guess that somehow the SSL authentication failed. As an experiment I tried deliberatly putting garbage certificate and key file names (e.g. "client-2048_XXX.crt") but saw no difference in the response from betfair or any of the curl diagnostics (set up via curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace);
and curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
). So I have no way of knowing for sure the libcurl has processed my cert and key files properly. Indeed I am even suspecting that perhaps it is not processing them at all - perhaps I'm missing some other option along the lines of CURLOPT_PLEASE_USE_SSL_AUTHENTICATION which is resulting in the files being ignored?
EDIT: So for the record, the full sequence looks like this (some text hidden):
curl_easy_setopt(curl, CURLOPT_URL, "https://identitysso.betfair.com/api/certlogin");
curl_easy_setopt(curl, CURLOPT_SSLCERT,"client-2048.crt");
curl_easy_setopt(curl, CURLOPT_SSLKEY,"client-2048.key");
curl_easy_setopt(curl, CURLOPT_POST, 1);
struct curl_slist *chunk = NULL;
chunk = curl_slist_append(chunk, "X-Application: _HIDDEN_");
chunk = curl_slist_append(chunk,"Content-Type: application/x-www-form-urlencoded");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS,"username=_HIDDEN_&password=_HIDDEN_");
curl_easy_perform(curl);
EDIT: I thought that perhaps I somehow compiled my libcurl without SSL. To check this I called curl_version_info, which amongst other things gives you:
char *ssl_version; /* human readable string */
Printing this out gave the string "WinSSL" which I assume means that SSL is included.
EDIT: FYI, I have four "client-2048" files, a .crt, .pem, .key and .csr. They all sit on the same directory as my exe file. I also print out the current working directory (as reported by _getcwd()) at run time just do double check that my exe is running from the right location.
EDIT: Here is my working login.sh (please excuse it's inelegance, I was hacking with cut and paste code and scarcely knew what I was doing). getlog.exe was a tiny utility I wrote to do some string manipulation on some JSON.
#!/bin/bash
# uses rescript
APP_KEY=_HIDDEN_
#SESSION_TOKEN=$2
HOST=https://api.betfair.com/exchange/betting
AUTHURL=https://identitysso.betfair.com/api/certlogin
CURL=curl
function bflogin()
{
echo "bflogin()"
OUT=$($CURL -s -k --cert client-2048.crt --key client-2048.key --data "username=_HIDDEN_&password=_HIDDEN_" -H "X-Application: $APP_KEY" -H "Content-Type: application/x-www-form-urlencoded" $AUTHURL)
echo $OUT
SESSION_TOKEN=$(echo $OUT | getlog.exe)
echo
echo "Here -> "$SESSION_TOKEN
echo $SESSION_TOKEN > st.txt
}