Newer
Older
do {
entry = PR_ReadDir(dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN);
Daniel Stenberg
committed
if(entry) {
char fullpath[PATH_MAX];
snprintf(fullpath, sizeof(fullpath), "%s/%s", data->set.ssl.CApath,
entry->name);
rc = nss_load_cert(fullpath, PR_TRUE);
/* FIXME: check this return value! */
}
/* This is purposefully tolerant of errors so non-PEM files
* can be in the same directory */
Daniel Stenberg
committed
} while(entry != NULL);
PR_CloseDir(dir);
}
}
infof(data,
" CAfile: %s\n"
" CApath: %s\n",
data->set.ssl.CAfile ? data->set.ssl.CAfile : "none",
data->set.ssl.CApath ? data->set.ssl.CApath : "none");
Daniel Stenberg
committed
if (data->set.ssl.CRLfile) {
int rc = nss_load_crl(data->set.ssl.CRLfile, PR_FALSE);
if (!rc) {
curlerr = CURLE_SSL_CRL_BADFILE;
goto error;
}
infof(data,
" CRLfile: %s\n",
data->set.ssl.CRLfile ? data->set.ssl.CRLfile : "none");
}
Daniel Stenberg
committed
if(data->set.str[STRING_CERT]) {
char *n;
char *nickname;
nickname = (char *)malloc(PATH_MAX);
if(is_file(data->set.str[STRING_CERT])) {
n = strrchr(data->set.str[STRING_CERT], '/');
Daniel Stenberg
committed
if(n) {
n++; /* skip last slash */
snprintf(nickname, PATH_MAX, "PEM Token #%ld:%s", 1, n);
}
}
else {
strncpy(nickname, data->set.str[STRING_CERT], PATH_MAX);
}
if(nss_Init_Tokens(conn) != SECSuccess) {
free(nickname);
goto error;
}
Daniel Stenberg
committed
if(!cert_stuff(conn, data->set.str[STRING_CERT],
data->set.str[STRING_KEY])) {
/* failf() is already done in cert_stuff() */
free(nickname);
return CURLE_SSL_CERTPROBLEM;
}
connssl->client_nickname = strdup(nickname);
if(SSL_GetClientAuthDataHook(model,
(SSLGetClientAuthData) SelectClientCert,
(void *)connssl->client_nickname) !=
SECSuccess) {
curlerr = CURLE_SSL_CERTPROBLEM;
goto error;
}
free(nickname);
PK11_SetPasswordFunc(nss_no_password);
}
else
connssl->client_nickname = NULL;
/* Import our model socket onto the existing file descriptor */
connssl->handle = PR_ImportTCPSocket(sockfd);
connssl->handle = SSL_ImportFD(model, connssl->handle);
if(!connssl->handle)
goto error;
PR_Close(model); /* We don't need this any more */
/* Force handshake on next I/O */
SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE);
SSL_SetURL(connssl->handle, conn->host.name);
Daniel Stenberg
committed
if(SSL_ForceHandshakeWithTimeout(connssl->handle,
PR_SecondsToInterval(HANDSHAKE_TIMEOUT))
!= SECSuccess) {
Daniel Stenberg
committed
if(conn->data->set.ssl.certverifyresult!=0)
curlerr = CURLE_SSL_CACERT;
}
Daniel Stenberg
committed
connssl->state = ssl_connection_complete;
display_conn_info(conn, connssl->handle);
return CURLE_OK;
error:
err = PR_GetError();
infof(data, "NSS error %d\n", err);
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
if(model)
PR_Close(model);
return curlerr;
}
/* return number of sent (non-SSL) bytes */
int Curl_nss_send(struct connectdata *conn, /* connection data */
int sockindex, /* socketindex */
void *mem, /* send this data */
size_t len) /* amount to write */
{
PRInt32 err;
struct SessionHandle *data = conn->data;
PRInt32 timeout;
int rc;
if(data->set.timeout)
timeout = PR_MillisecondsToInterval(data->set.timeout);
else
timeout = PR_MillisecondsToInterval(DEFAULT_CONNECT_TIMEOUT);
rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0, timeout);
if(rc < 0) {
err = PR_GetError();
if(err == PR_IO_TIMEOUT_ERROR) {
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
Daniel Stenberg
committed
failf(conn->data, "SSL write: error %d", err);
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
return -1;
}
return rc; /* number of bytes */
}
/*
* If the read would block we return -1 and set 'wouldblock' to TRUE.
* Otherwise we return the amount of data read. Other errors should return -1
* and set 'wouldblock' to FALSE.
*/
ssize_t Curl_nss_recv(struct connectdata * conn, /* connection data */
int num, /* socketindex */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
bool * wouldblock)
{
ssize_t nread;
struct SessionHandle *data = conn->data;
PRInt32 timeout;
if(data->set.timeout)
timeout = PR_SecondsToInterval(data->set.timeout);
else
timeout = PR_MillisecondsToInterval(DEFAULT_CONNECT_TIMEOUT);
nread = PR_Recv(conn->ssl[num].handle, buf, (int)buffersize, 0, timeout);
*wouldblock = FALSE;
if(nread < 0) {
/* failed SSL read */
PRInt32 err = PR_GetError();
if(err == PR_WOULD_BLOCK_ERROR) {
*wouldblock = TRUE;
return -1; /* basically EWOULDBLOCK */
}
if(err == PR_IO_TIMEOUT_ERROR) {
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
failf(conn->data, "SSL read: errno %d", err);
return -1;
}
return nread;
}
size_t Curl_nss_version(char *buffer, size_t size)
{
return snprintf(buffer, size, "NSS/%s", NSS_VERSION);
}
#endif /* USE_NSS */