static void tcpkeepalive(struct SessionHandle *data, curl_socket_t sockfd) { int optval = data->set.tcp_keepalive?1:0; /* only set IDLE and INTVL if setting KEEPALIVE is successful */ if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&optval, sizeof(optval)) < 0) { infof(data, "Failed to set SO_KEEPALIVE on fd %d\n", sockfd); } else { #ifdef TCP_KEEPIDLE optval = curlx_sltosi(data->set.tcp_keepidle); KEEPALIVE_FACTOR(optval); if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&optval, sizeof(optval)) < 0) { infof(data, "Failed to set TCP_KEEPIDLE on fd %d\n", sockfd); } #endif #ifdef TCP_KEEPINTVL optval = curlx_sltosi(data->set.tcp_keepintvl); KEEPALIVE_FACTOR(optval); if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&optval, sizeof(optval)) < 0) { infof(data, "Failed to set TCP_KEEPINTVL on fd %d\n", sockfd); } #endif } }
static void tcpkeepalive(struct Curl_easy *data, curl_socket_t sockfd) { int optval = data->set.tcp_keepalive?1:0; /* only set IDLE and INTVL if setting KEEPALIVE is successful */ if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&optval, sizeof(optval)) < 0) { infof(data, "Failed to set SO_KEEPALIVE on fd %d\n", sockfd); } else { #if defined(SIO_KEEPALIVE_VALS) struct tcp_keepalive vals; DWORD dummy; vals.onoff = 1; optval = curlx_sltosi(data->set.tcp_keepidle); KEEPALIVE_FACTOR(optval); vals.keepalivetime = optval; optval = curlx_sltosi(data->set.tcp_keepintvl); KEEPALIVE_FACTOR(optval); vals.keepaliveinterval = optval; if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals), NULL, 0, &dummy, NULL, NULL) != 0) { infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d\n", (int)sockfd, WSAGetLastError()); } #elif defined(CURL_WINDOWS_APP) (void)majorVersion; detectOsState = DETECT_OS_VISTA_OR_LATER; #else #ifdef TCP_KEEPIDLE optval = curlx_sltosi(data->set.tcp_keepidle); KEEPALIVE_FACTOR(optval); if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&optval, sizeof(optval)) < 0) { infof(data, "Failed to set TCP_KEEPIDLE on fd %d\n", sockfd); } #endif #ifdef TCP_KEEPINTVL optval = curlx_sltosi(data->set.tcp_keepintvl); KEEPALIVE_FACTOR(optval); if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&optval, sizeof(optval)) < 0) { infof(data, "Failed to set TCP_KEEPINTVL on fd %d\n", sockfd); } #endif #ifdef TCP_KEEPALIVE /* Mac OS X style */ optval = curlx_sltosi(data->set.tcp_keepidle); KEEPALIVE_FACTOR(optval); if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE, (void *)&optval, sizeof(optval)) < 0) { infof(data, "Failed to set TCP_KEEPALIVE on fd %d\n", sockfd); } #endif #endif } }
/*********************************************************************** * * smtp_endofresp() * * Checks for an ending SMTP status code at the start of the given string, but * also detects various capabilities from the EHLO response including the * supported authentication mechanisms. */ static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len, int *resp) { struct smtp_conn *smtpc = &conn->proto.smtpc; bool result = FALSE; /* Nothing for us */ if(len < 4 || !ISDIGIT(line[0]) || !ISDIGIT(line[1]) || !ISDIGIT(line[2])) return FALSE; /* Do we have a command response? This should be the response code followed by a space and optionally some text as per RFC-5321 and as outlined in Section 4. Examples of RFC-4954 but some e-mail servers ignore this and only send the response code instead as per Section 4.2. */ if(line[3] == ' ' || len == 5) { result = TRUE; *resp = curlx_sltosi(strtol(line, NULL, 10)); /* Make sure real server never sends internal value */ if(*resp == 1) *resp = 0; } /* Do we have a multiline (continuation) response? */ else if(line[3] == '-' && (smtpc->state == SMTP_EHLO || smtpc->state == SMTP_COMMAND)) { result = TRUE; *resp = 1; /* Internal response code */ } return result; }
/* Function that checks for an ending smtp status code at the start of the given string. As a side effect, it also flags allowed authentication mechanisms according to EHLO AUTH response. */ static int smtp_endofresp(struct pingpong *pp, int *resp) { char *line = pp->linestart_resp; size_t len = pp->nread_resp; struct connectdata *conn = pp->conn; struct smtp_conn *smtpc = &conn->proto.smtpc; int result; size_t wordlen; if(len < 4 || !ISDIGIT(line[0]) || !ISDIGIT(line[1]) || !ISDIGIT(line[2])) return FALSE; /* Nothing for us. */ if((result = (line[3] == ' ')) != 0) *resp = curlx_sltosi(strtol(line, NULL, 10)); line += 4; len -= 4; if(smtpc->state == SMTP_EHLO && len >= 5 && !memcmp(line, "AUTH ", 5)) { line += 5; len -= 5; for(;;) { while(len && (*line == ' ' || *line == '\t' || *line == '\r' || *line == '\n')) { line++; len--; } if(!len) break; for(wordlen = 0; wordlen < len && line[wordlen] != ' ' && line[wordlen] != '\t' && line[wordlen] != '\r' && line[wordlen] != '\n';) wordlen++; if(wordlen == 5 && !memcmp(line, "LOGIN", 5)) smtpc->authmechs |= SMTP_AUTH_LOGIN; else if(wordlen == 5 && !memcmp(line, "PLAIN", 5)) smtpc->authmechs |= SMTP_AUTH_PLAIN; else if(wordlen == 8 && !memcmp(line, "CRAM-MD5", 8)) smtpc->authmechs |= SMTP_AUTH_CRAM_MD5; else if(wordlen == 10 && !memcmp(line, "DIGEST-MD5", 10)) smtpc->authmechs |= SMTP_AUTH_DIGEST_MD5; else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6)) smtpc->authmechs |= SMTP_AUTH_GSSAPI; else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8)) smtpc->authmechs |= SMTP_AUTH_EXTERNAL; else if(wordlen == 4 && !memcmp(line, "NTLM", 4)) smtpc->authmechs |= SMTP_AUTH_NTLM; line += wordlen; len -= wordlen; } } return result; }
int Curl_parsedate(const char *date, time_t *output) { time_t t = 0; int wdaynum=-1; /* day of the week number, 0-6 (mon-sun) */ int monnum=-1; /* month of the year number, 0-11 */ int mdaynum=-1; /* day of month, 1 - 31 */ int hournum=-1; int minnum=-1; int secnum=-1; int yearnum=-1; int tzoff=-1; struct my_tm tm; enum assume dignext = DATE_MDAY; const char *indate = date; /* save the original pointer */ int part = 0; /* max 6 parts */ while(*date && (part < 6)) { bool found=FALSE; skip(&date); if(ISALPHA(*date)) { /* a name coming up */ char buf[32]=""; size_t len; sscanf(date, "%31[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]", buf); len = strlen(buf); if(wdaynum == -1) { wdaynum = checkday(buf, len); if(wdaynum != -1) found = TRUE; } if(!found && (monnum == -1)) { monnum = checkmonth(buf); if(monnum != -1) found = TRUE; } if(!found && (tzoff == -1)) { /* this just must be a time zone string */ tzoff = checktz(buf); if(tzoff != -1) found = TRUE; } if(!found) return PARSEDATE_FAIL; /* bad string */ date += len; } else if(ISDIGIT(*date)) { /* a digit */ int val; char *end; if((secnum == -1) && (3 == sscanf(date, "%02d:%02d:%02d", &hournum, &minnum, &secnum))) { /* time stamp! */ date += 8; } else if((secnum == -1) && (2 == sscanf(date, "%02d:%02d", &hournum, &minnum))) { /* time stamp without seconds */ date += 5; secnum = 0; } else { val = curlx_sltosi(strtol(date, &end, 10)); if((tzoff == -1) && ((end - date) == 4) && (val <= 1400) && (indate< date) && ((date[-1] == '+' || date[-1] == '-'))) { /* four digits and a value less than or equal to 1400 (to take into account all sorts of funny time zone diffs) and it is preceeded with a plus or minus. This is a time zone indication. 1400 is picked since +1300 is frequently used and +1400 is mentioned as an edge number in the document "ISO C 200X Proposal: Timezone Functions" at http://david.tribble.com/text/c0xtimezone.html If anyone has a more authoritative source for the exact maximum time zone offsets, please speak up! */ found = TRUE; tzoff = (val/100 * 60 + val%100)*60; /* the + and - prefix indicates the local time compared to GMT, this we need ther reversed math to get what we want */ tzoff = date[-1]=='+'?-tzoff:tzoff; } if(((end - date) == 8) && (yearnum == -1) && (monnum == -1) && (mdaynum == -1)) { /* 8 digits, no year, month or day yet. This is YYYYMMDD */ found = TRUE; yearnum = val/10000; monnum = (val%10000)/100-1; /* month is 0 - 11 */ mdaynum = val%100; } if(!found && (dignext == DATE_MDAY) && (mdaynum == -1)) { if((val > 0) && (val<32)) { mdaynum = val; found = TRUE; } dignext = DATE_YEAR; } if(!found && (dignext == DATE_YEAR) && (yearnum == -1)) { yearnum = val; found = TRUE; if(yearnum < 1900) { if(yearnum > 70) yearnum += 1900; else yearnum += 2000; } if(mdaynum == -1) dignext = DATE_MDAY; } if(!found) return PARSEDATE_FAIL; date = end; } } part++; } if(-1 == secnum) secnum = minnum = hournum = 0; /* no time, make it zero */ if((-1 == mdaynum) || (-1 == monnum) || (-1 == yearnum)) /* lacks vital info, fail */ return PARSEDATE_FAIL; #if SIZEOF_TIME_T < 5 /* 32 bit time_t can only hold dates to the beginning of 2038 */ if(yearnum > 2037) { *output = 0x7fffffff; return PARSEDATE_LATER; } #endif if(yearnum < 1970) { *output = 0; return PARSEDATE_SOONER; } tm.tm_sec = secnum; tm.tm_min = minnum; tm.tm_hour = hournum; tm.tm_mday = mdaynum; tm.tm_mon = monnum; tm.tm_year = yearnum - 1900; /* my_timegm() returns a time_t. time_t is often 32 bits, even on many architectures that feature 64 bit 'long'. Some systems have 64 bit time_t and deal with years beyond 2038. However, even on some of the systems with 64 bit time_t mktime() returns -1 for dates beyond 03:14:07 UTC, January 19, 2038. (Such as AIX 5100-06) */ t = my_timegm(&tm); /* time zone adjust (cast t to int to compare to negative one) */ if(-1 != (int)t) { /* Add the time zone diff between local time zone and GMT. */ long delta = (long)(tzoff!=-1?tzoff:0); if((delta>0) && (t + delta < t)) return -1; /* time_t overflow */ t += delta; } *output = t; return PARSEDATE_OK; }
/* Function that checks for an ending SMTP status code at the start of the given string, but also detects various capabilities from the EHLO response including the supported authentication mechanisms. */ static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len, int *resp) { struct smtp_conn *smtpc = &conn->proto.smtpc; bool result = FALSE; size_t wordlen; if(len < 4 || !ISDIGIT(line[0]) || !ISDIGIT(line[1]) || !ISDIGIT(line[2])) return FALSE; /* Nothing for us */ /* Do we have a command response? */ result = (line[3] == ' ') ? TRUE : FALSE; if(result) *resp = curlx_sltosi(strtol(line, NULL, 10)); /* Are we processing EHLO command data? */ if(smtpc->state == SMTP_EHLO && (!result || (result && *resp/100 == 2))) { line += 4; len -= 4; /* Does the server support the STARTTLS capability? */ if(len >= 8 && !memcmp(line, "STARTTLS", 8)) smtpc->tls_supported = TRUE; /* Does the server support the SIZE capability? */ else if(len >= 4 && !memcmp(line, "SIZE", 4)) smtpc->size_supported = TRUE; /* Do we have the authentication mechanism list? */ else if(len >= 5 && !memcmp(line, "AUTH ", 5)) { line += 5; len -= 5; /* Loop through the data line */ for(;;) { while(len && (*line == ' ' || *line == '\t' || *line == '\r' || *line == '\n')) { line++; len--; } if(!len) break; /* Extract the word */ for(wordlen = 0; wordlen < len && line[wordlen] != ' ' && line[wordlen] != '\t' && line[wordlen] != '\r' && line[wordlen] != '\n';) wordlen++; /* Test the word for a matching authentication mechanism */ if(wordlen == 5 && !memcmp(line, "LOGIN", 5)) smtpc->authmechs |= SASL_MECH_LOGIN; else if(wordlen == 5 && !memcmp(line, "PLAIN", 5)) smtpc->authmechs |= SASL_MECH_PLAIN; else if(wordlen == 8 && !memcmp(line, "CRAM-MD5", 8)) smtpc->authmechs |= SASL_MECH_CRAM_MD5; else if(wordlen == 10 && !memcmp(line, "DIGEST-MD5", 10)) smtpc->authmechs |= SASL_MECH_DIGEST_MD5; else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6)) smtpc->authmechs |= SASL_MECH_GSSAPI; else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8)) smtpc->authmechs |= SASL_MECH_EXTERNAL; else if(wordlen == 4 && !memcmp(line, "NTLM", 4)) smtpc->authmechs |= SASL_MECH_NTLM; line += wordlen; len -= wordlen; } } } return result; }
static int parsedate(const char *date, time_t *output) { time_t t = 0; int wdaynum = -1; /* day of the week number, 0-6 (mon-sun) */ int monnum = -1; /* month of the year number, 0-11 */ int mdaynum = -1; /* day of month, 1 - 31 */ int hournum = -1; int minnum = -1; int secnum = -1; int yearnum = -1; int tzoff = -1; struct my_tm tm; enum assume dignext = DATE_MDAY; const char *indate = date; /* save the original pointer */ int part = 0; /* max 6 parts */ while(*date && (part < 6)) { bool found = FALSE; skip(&date); if(ISALPHA(*date)) { /* a name coming up */ char buf[32]=""; size_t len; if(sscanf(date, "%31[ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz]", buf)) len = strlen(buf); else len = 0; if(wdaynum == -1) { wdaynum = checkday(buf, len); if(wdaynum != -1) found = TRUE; } if(!found && (monnum == -1)) { monnum = checkmonth(buf); if(monnum != -1) found = TRUE; } if(!found && (tzoff == -1)) { /* this just must be a time zone string */ tzoff = checktz(buf); if(tzoff != -1) found = TRUE; } if(!found) return PARSEDATE_FAIL; /* bad string */ date += len; } else if(ISDIGIT(*date)) { /* a digit */ int val; char *end; int len = 0; if((secnum == -1) && (3 == sscanf(date, "%02d:%02d:%02d%n", &hournum, &minnum, &secnum, &len))) { /* time stamp! */ date += len; } else if((secnum == -1) && (2 == sscanf(date, "%02d:%02d%n", &hournum, &minnum, &len))) { /* time stamp without seconds */ date += len; secnum = 0; } else { long lval; int error; int old_errno; old_errno = errno; errno = 0; lval = strtol(date, &end, 10); error = errno; if(errno != old_errno) errno = old_errno; if(error) return PARSEDATE_FAIL; #if LONG_MAX != INT_MAX if((lval > (long)INT_MAX) || (lval < (long)INT_MIN)) return PARSEDATE_FAIL; #endif val = curlx_sltosi(lval); if((tzoff == -1) && ((end - date) == 4) && (val <= 1400) && (indate< date) && ((date[-1] == '+' || date[-1] == '-'))) { /* four digits and a value less than or equal to 1400 (to take into account all sorts of funny time zone diffs) and it is preceded with a plus or minus. This is a time zone indication. 1400 is picked since +1300 is frequently used and +1400 is mentioned as an edge number in the document "ISO C 200X Proposal: Timezone Functions" at http://david.tribble.com/text/c0xtimezone.html If anyone has a more authoritative source for the exact maximum time zone offsets, please speak up! */ found = TRUE; tzoff = (val/100 * 60 + val%100)*60; /* the + and - prefix indicates the local time compared to GMT, this we need their reversed math to get what we want */ tzoff = date[-1]=='+'?-tzoff:tzoff; } if(((end - date) == 8) && (yearnum == -1) && (monnum == -1) && (mdaynum == -1)) { /* 8 digits, no year, month or day yet. This is YYYYMMDD */ found = TRUE; yearnum = val/10000; monnum = (val%10000)/100-1; /* month is 0 - 11 */ mdaynum = val%100; } if(!found && (dignext == DATE_MDAY) && (mdaynum == -1)) { if((val > 0) && (val<32)) { mdaynum = val; found = TRUE; } dignext = DATE_YEAR; } if(!found && (dignext == DATE_YEAR) && (yearnum == -1)) { yearnum = val; found = TRUE; if(yearnum < 100) { if(yearnum > 70) yearnum += 1900; else yearnum += 2000; } if(mdaynum == -1) dignext = DATE_MDAY; } if(!found) return PARSEDATE_FAIL; date = end; } } part++; } if(-1 == secnum) secnum = minnum = hournum = 0; /* no time, make it zero */ if((-1 == mdaynum) || (-1 == monnum) || (-1 == yearnum)) /* lacks vital info, fail */ return PARSEDATE_FAIL; #ifdef HAVE_TIME_T_UNSIGNED if(yearnum < 1970) { /* only positive numbers cannot return earlier */ *output = TIME_T_MIN; return PARSEDATE_SOONER; } #endif #if (SIZEOF_TIME_T < 5) #ifdef HAVE_TIME_T_UNSIGNED /* an unsigned 32 bit time_t can only hold dates to 2106 */ if(yearnum > 2105) { *output = TIME_T_MAX; return PARSEDATE_LATER; } #else /* a signed 32 bit time_t can only hold dates to the beginning of 2038 */ if(yearnum > 2037) { *output = TIME_T_MAX; return PARSEDATE_LATER; } if(yearnum < 1903) { *output = TIME_T_MIN; return PARSEDATE_SOONER; } #endif #else /* The Gregorian calendar was introduced 1582 */ if(yearnum < 1583) return PARSEDATE_FAIL; #endif if((mdaynum > 31) || (monnum > 11) || (hournum > 23) || (minnum > 59) || (secnum > 60)) return PARSEDATE_FAIL; /* clearly an illegal date */ tm.tm_sec = secnum; tm.tm_min = minnum; tm.tm_hour = hournum; tm.tm_mday = mdaynum; tm.tm_mon = monnum; tm.tm_year = yearnum; /* my_timegm() returns a time_t. time_t is often 32 bits, sometimes even on architectures that feature 64 bit 'long' but ultimately time_t is the correct data type to use. */ my_timegm(&tm, &t); /* Add the time zone diff between local time zone and GMT. */ if(tzoff == -1) tzoff = 0; if((tzoff > 0) && (t > TIME_T_MAX - tzoff)) { *output = TIME_T_MAX; return PARSEDATE_LATER; /* time_t overflow */ } t += tzoff; *output = t; return PARSEDATE_OK; }
/* Function that checks for an ending smtp status code at the start of the given string, but also detects the supported authentication mechanisms from the EHLO AUTH response. */ static int smtp_endofresp(struct pingpong *pp, int *resp) { char *line = pp->linestart_resp; size_t len = pp->nread_resp; struct connectdata *conn = pp->conn; struct smtp_conn *smtpc = &conn->proto.smtpc; int result; size_t wordlen; if(len < 4 || !ISDIGIT(line[0]) || !ISDIGIT(line[1]) || !ISDIGIT(line[2])) return FALSE; /* Nothing for us */ /* Extract the response code if necessary */ if((result = (line[3] == ' ')) != 0) *resp = curlx_sltosi(strtol(line, NULL, 10)); line += 4; len -= 4; /* Do we have a SIZE capability? */ if(smtpc->state == SMTP_EHLO && len >= 4 && !memcmp(line, "SIZE", 4)) { DEBUGF(infof(conn->data, "Server supports SIZE extension.\n")); smtpc->size_supported = true; } /* Do we have an AUTH capability? */ if(smtpc->state == SMTP_EHLO && len >= 5 && !memcmp(line, "AUTH ", 5)) { line += 5; len -= 5; for(;;) { while(len && (*line == ' ' || *line == '\t' || *line == '\r' || *line == '\n')) { line++; len--; } if(!len) break; /* Extract the word */ for(wordlen = 0; wordlen < len && line[wordlen] != ' ' && line[wordlen] != '\t' && line[wordlen] != '\r' && line[wordlen] != '\n';) wordlen++; /* Test the word for a matching authentication mechanism */ if(wordlen == 5 && !memcmp(line, "LOGIN", 5)) smtpc->authmechs |= SASL_MECH_LOGIN; else if(wordlen == 5 && !memcmp(line, "PLAIN", 5)) smtpc->authmechs |= SASL_MECH_PLAIN; else if(wordlen == 8 && !memcmp(line, "CRAM-MD5", 8)) smtpc->authmechs |= SASL_MECH_CRAM_MD5; else if(wordlen == 10 && !memcmp(line, "DIGEST-MD5", 10)) smtpc->authmechs |= SASL_MECH_DIGEST_MD5; else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6)) smtpc->authmechs |= SASL_MECH_GSSAPI; else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8)) smtpc->authmechs |= SASL_MECH_EXTERNAL; else if(wordlen == 4 && !memcmp(line, "NTLM", 4)) smtpc->authmechs |= SASL_MECH_NTLM; line += wordlen; len -= wordlen; } } return result; }