static int traverse_string(const unsigned char *p, int len, int inform, int (*rfunc) (unsigned long value, void *in), void *arg) { unsigned long value; int ret; while (len) { if (inform == MBSTRING_ASC) { value = *p++; len--; } else if (inform == MBSTRING_BMP) { value = *p++ << 8; value |= *p++; len -= 2; } else if (inform == MBSTRING_UNIV) { value = ((unsigned long)*p++) << 24; value |= ((unsigned long)*p++) << 16; value |= *p++ << 8; value |= *p++; len -= 4; } else { ret = UTF8_getc(p, len, &value); if (ret < 0) return -1; len -= ret; p += ret; } if (rfunc) { ret = rfunc(value, arg); if (ret <= 0) return ret; } } return 1; }
void rec_cal(int fc) { int rec_num = g_fa[fc].rec_num; int shared_mem_id; int *shared_mem_ptr; int *ans; int ans_count; shared_mem_id = shmget(IPC_PRIVATE, rec_num * sizeof(int), IPC_CREAT); if ((shared_mem_ptr = shmat(shared_mem_id, NULL, 0)) == (void*)-1) { return; } ans = (int*)shared_mem_ptr; for (ans_count = 0; ans_count < rec_num; ans_count++) { pid_t child_pid; child_pid = fork(); if (child_pid == 0) { *(ans + ans_count) = rfunc(g_fa[fc].rec_locate[ans_count]); // printf("%d\n",*(ans + ans_count)); exit(0); } } for (ans_count = 0; ans_count < rec_num; ans_count++) { wait(NULL); } for (ans_count = 0; ans_count < rec_num; ans_count++) { g_fa[fc].rec_locate[ans_count]->type = CHILD_ANS; g_fa[fc].rec_locate[ans_count]->result = *(ans + ans_count); // printf("ans %d\n", *(ans + ans_count)); } }
static int traverse_string(const unsigned char *p, int len, int inform, int (*rfunc)(unsigned long value, void *in), void *arg) { unsigned long value; int ret; while (len) { switch (inform) { case MBSTRING_ASC: value = *p++; len--; break; case MBSTRING_BMP: value = *p++ << 8; value |= *p++; /* BMP is explictly defined to not support surrogates */ if (UNICODE_IS_SURROGATE(value)) return -1; len -= 2; break; case MBSTRING_UNIV: value = (unsigned long)*p++ << 24; value |= *p++ << 16; value |= *p++ << 8; value |= *p++; if (value > UNICODE_MAX || UNICODE_IS_SURROGATE(value)) return -1; len -= 4; break; default: ret = UTF8_getc(p, len, &value); if (ret < 0) return -1; len -= ret; p += ret; break; } if (rfunc) { ret = rfunc(value, arg); if (ret <= 0) return ret; } } return 1; }
int tls_bio(ACL_SOCKET fd, int timeout, TLS_SESS_STATE *TLScontext, int (*hsfunc) (SSL *), int (*rfunc) (SSL *, void *, int), int (*wfunc) (SSL *, const void *, int), void *buf, int num) { const char *myname = "tls_bio"; int status = 0; int err; int retval = 0; int biop_retval; int done; /* * If necessary, retry the SSL handshake or read/write operation after * handling any pending network I/O. */ for (done = 0; done == 0; /* void */ ) { if (hsfunc) { #if 1 status = hsfunc(TLScontext->con); #else status = SSL_do_handshake(TLScontext->con); #endif } else if (rfunc) status = rfunc(TLScontext->con, buf, num); else if (wfunc) status = wfunc(TLScontext->con, buf, num); else acl_msg_panic("%s: nothing to do here", myname); err = SSL_get_error(TLScontext->con, status); #if (OPENSSL_VERSION_NUMBER <= 0x0090581fL) /* * There is a bug up to and including OpenSSL-0.9.5a: if an error * occurs while checking the peers certificate due to some * certificate error (e.g. as happend with a RSA-padding error), the * error is put onto the error stack. If verification is not * enforced, this error should be ignored, but the error-queue is not * cleared, so we can find this error here. The bug has been fixed on * May 28, 2000. * * This bug so far has only manifested as 4800:error:0407006A:rsa * routines:RSA_padding_check_PKCS1_type_1:block type is not * 01:rsa_pk1.c:100: 4800:error:04067072:rsa * routines:RSA_EAY_PUBLIC_DECRYPT:padding check * failed:rsa_eay.c:396: 4800:error:0D079006:asn1 encoding * routines:ASN1_verify:bad get asn1 object call:a_verify.c:109: so * that we specifically test for this error. We print the errors to * the logfile and automatically clear the error queue. Then we retry * to get another error code. We cannot do better, since we can only * retrieve the last entry of the error-queue without actually * cleaning it on the way. * * This workaround is secure, as verify_result is set to "failed" * anyway. */ if (err == SSL_ERROR_SSL) { if (ERR_peek_error() == 0x0407006AL) { tls_print_errors(); acl_msg_info("OpenSSL <= 0.9.5a workaround called: certificate errors ignored"); err = SSL_get_error(TLScontext->con, status); } } #endif /* * Find out if we must retry the operation and/or if there is pending * network I/O. * * XXX If we're the first to invoke SSL_shutdown(), then the operation * isn't really complete when the call returns. We could hide that * anomaly here and repeat the call. */ switch (err) { case SSL_ERROR_NONE: /* success */ retval = status; done = 1; /* FALLTHROUGH */ case SSL_ERROR_WANT_WRITE: /* flush/update buffers */ case SSL_ERROR_WANT_READ: biop_retval = network_biopair_interop(fd, timeout, TLScontext->network_bio); if (biop_retval < 0) return (-1); /* network read/write error */ break; /* * With tls_timed_read() and tls_timed_write() the caller is the * VSTREAM library module which is unaware of TLS, so we log the * TLS error stack here. In a better world, each VSTREAM I/O * object would provide an error reporting method in addition to * the timed_read and timed_write methods, so that we would not * need to have ad-hoc code like this. */ case SSL_ERROR_SSL: if (rfunc || wfunc) tls_print_errors(); /* FALLTHROUGH */ default: retval = status; done = 1; break; } } return (retval); }
ssize_t _WS_recv(int recvf, int sockfd, const void *buf, size_t len, int flags) { int rawcount, deccount, left, rawlen, retlen, decodelen; int sockflags; int i; char * fstart, * fend, * cstart; static void * (*rfunc)(), * (*rfunc2)(); if (!rfunc) rfunc = (void *(*)()) dlsym(RTLD_NEXT, "recv"); if (!rfunc2) rfunc2 = (void *(*)()) dlsym(RTLD_NEXT, "read"); if (len == 0) { return 0; } if ((_WS_sockfd == 0) || (_WS_sockfd != sockfd)) { // Not our file descriptor, just pass through if (recvf) { return (ssize_t) rfunc(sockfd, buf, len, flags); } else { return (ssize_t) rfunc2(sockfd, buf, len); } } DEBUG("_WS_recv(%d, _, %d) called\n", sockfd, len); sockflags = fcntl(sockfd, F_GETFL, 0); left = len; retlen = 0; // first copy in any carry-over bytes if (_WS_rcarry_cnt) { if (_WS_rcarry_cnt == 1) { DEBUG("Using carry byte: %u (", _WS_rcarry[0]); } else if (_WS_rcarry_cnt == 2) { DEBUG("Using carry bytes: %u,%u (", _WS_rcarry[0], _WS_rcarry[1]); } else { RET_ERROR(EIO, "Too many carry-over bytes\n"); } if (len <= _WS_rcarry_cnt) { DEBUG("final)\n"); memcpy((char *) buf, _WS_rcarry, len); _WS_rcarry_cnt -= len; return len; } else { DEBUG("prepending)\n"); memcpy((char *) buf, _WS_rcarry, _WS_rcarry_cnt); retlen += _WS_rcarry_cnt; left -= _WS_rcarry_cnt; _WS_rcarry_cnt = 0; } } // Determine the number of base64 encoded bytes needed rawcount = (left * 4) / 3 + 3; rawcount -= rawcount%4; if (rawcount > _WS_bufsize - 1) { RET_ERROR(ENOMEM, "recv of %d bytes is larger than buffer\n", rawcount); } i = 0; while (1) { // Peek at everything available rawlen = (int) rfunc(sockfd, _WS_rbuf, _WS_bufsize-1, flags | MSG_PEEK); if (rawlen <= 0) { DEBUG("_WS_recv: returning because rawlen %d\n", rawlen); return (ssize_t) rawlen; } fstart = _WS_rbuf; /* while (rawlen >= 2 && fstart[0] == '\x00' && fstart[1] == '\xff') { fstart += 2; rawlen -= 2; } */ if (rawlen >= 2 && fstart[0] == '\x00' && fstart[1] == '\xff') { rawlen = (int) rfunc(sockfd, _WS_rbuf, 2, flags); if (rawlen != 2) { RET_ERROR(EIO, "Could not strip empty frame headers\n"); } continue; } fstart[rawlen] = '\x00'; if (rawlen - _WS_newframe >= 4) { // We have enough to base64 decode at least 1 byte break; } // Not enough to base64 decode if (sockflags & O_NONBLOCK) { // Just tell the caller to call again DEBUG("_WS_recv: returning because O_NONBLOCK, rawlen %d\n", rawlen); errno = EAGAIN; return -1; } // Repeat until at least 1 byte (4 raw bytes) to decode i++; if (i > 1000000) { MSG("Could not send final part of frame\n"); } } /* DEBUG("_WS_recv, left: %d, len: %d, rawlen: %d, newframe: %d, raw: ", left, len, rawlen, _WS_newframe); for (i = 0; i < rawlen; i++) { DEBUG("%u,", (unsigned char) ((char *) fstart)[i]); } DEBUG("\n"); */ if (_WS_newframe) { if (fstart[0] != '\x00') { RET_ERROR(EPROTO, "Missing frame start\n"); } fstart++; rawlen--; _WS_newframe = 0; } fend = memchr(fstart, '\xff', rawlen); if (fend) { _WS_newframe = 1; if ((fend - fstart) % 4) { RET_ERROR(EPROTO, "Frame length is not multiple of 4\n"); } } else { fend = fstart + rawlen - (rawlen % 4); if (fend - fstart < 4) { RET_ERROR(EPROTO, "Frame too short\n"); } } // How much should we consume if (rawcount < fend - fstart) { _WS_newframe = 0; deccount = rawcount; } else { deccount = fend - fstart; } // Now consume what we processed if (flags & MSG_PEEK) { MSG("*** Got MSG_PEEK ***\n"); } else { rfunc(sockfd, _WS_rbuf, fstart - _WS_rbuf + deccount + _WS_newframe, flags); } fstart[deccount] = '\x00'; // base64 terminator // Do direct base64 decode, instead of decode() decodelen = b64_pton(fstart, (char *) buf + retlen, deccount); if (decodelen <= 0) { RET_ERROR(EPROTO, "Base64 decode error\n"); } if (decodelen <= left) { retlen += decodelen; } else { retlen += left; if (! (flags & MSG_PEEK)) { // Add anything left over to the carry-over _WS_rcarry_cnt = decodelen - left; if (_WS_rcarry_cnt > 2) { RET_ERROR(EPROTO, "Got too much base64 data\n"); } memcpy(_WS_rcarry, buf + retlen, _WS_rcarry_cnt); if (_WS_rcarry_cnt == 1) { DEBUG("Saving carry byte: %u\n", _WS_rcarry[0]); } else if (_WS_rcarry_cnt == 2) { DEBUG("Saving carry bytes: %u,%u\n", _WS_rcarry[0], _WS_rcarry[1]); } else { MSG("Waah2!\n"); } } } ((char *) buf)[retlen] = '\x00'; /* DEBUG("*** recv %s as ", fstart); for (i = 0; i < retlen; i++) { DEBUG("%u,", (unsigned char) ((char *) buf)[i]); } DEBUG(" (%d -> %d): %d\n", deccount, decodelen, retlen); */ return retlen; }
int _WS_handshake(int sockfd) { int sz = 0, len, idx; int ret = -1, save_errno = EPROTO; char *last, *start, *end; long flags; char handshake[4096], response[4096], path[1024], prefix[5] = "", scheme[10] = "ws", host[1024], origin[1024], key1[100], key2[100], key3[9], chksum[17]; static void * (*rfunc)(), * (*wfunc)(); if (!rfunc) rfunc = (void *(*)()) dlsym(RTLD_NEXT, "recv"); if (!wfunc) wfunc = (void *(*)()) dlsym(RTLD_NEXT, "send"); DEBUG("_WS_handshake starting\n"); /* Disable NONBLOCK if set */ flags = fcntl(sockfd, F_GETFL, 0); if (flags & O_NONBLOCK) { fcntl(sockfd, F_SETFL, flags^O_NONBLOCK); } while (1) { len = (int) rfunc(sockfd, handshake+sz, 4095, 0); if (len < 1) { ret = len; save_errno = errno; break; } sz += len; handshake[sz] = '\x00'; if (sz < 4) { // Not enough yet continue; } if (strstr(handshake, "GET ") != handshake) { // We got something but it wasn't a WebSockets client break; } last = strstr(handshake, "\r\n\r\n"); if (! last) { continue; } if (! strstr(handshake, "Upgrade: WebSocket\r\n")) { MSG("Invalid WebSockets handshake\n"); break; } // Now parse out the data start = handshake+4; end = strstr(start, " HTTP/1.1"); if (!end) { break; } snprintf(path, end-start+1, "%s", start); start = strstr(handshake, "\r\nHost: "); if (!start) { break; } start += 8; end = strstr(start, "\r\n"); snprintf(host, end-start+1, "%s", start); start = strstr(handshake, "\r\nOrigin: "); if (!start) { break; } start += 10; end = strstr(start, "\r\n"); snprintf(origin, end-start+1, "%s", start); start = strstr(handshake, "\r\n\r\n") + 4; if (strlen(start) == 8) { sprintf(prefix, "Sec-"); snprintf(key3, 8+1, "%s", start); start = strstr(handshake, "\r\nSec-WebSocket-Key1: "); if (!start) { break; } start += 22; end = strstr(start, "\r\n"); snprintf(key1, end-start+1, "%s", start); start = strstr(handshake, "\r\nSec-WebSocket-Key2: "); if (!start) { break; } start += 22; end = strstr(start, "\r\n"); snprintf(key2, end-start+1, "%s", start); _WS_gen_md5(key1, key2, key3, chksum); //DEBUG("Got handshake (v76): %s\n", handshake); MSG("Got handshake (v76)\n"); } else { sprintf(prefix, ""); sprintf(key1, ""); sprintf(key2, ""); sprintf(key3, ""); sprintf(chksum, ""); //DEBUG("Got handshake (v75): %s\n", handshake); MSG("Got handshake (v75)\n"); } sprintf(response, _WS_response, prefix, origin, prefix, scheme, host, path, prefix, chksum); //DEBUG("Handshake response: %s\n", response); wfunc(sockfd, response, strlen(response), 0); save_errno = 0; ret = 0; break; } /* Re-enable NONBLOCK if it was set */ if (flags & O_NONBLOCK) { fcntl(sockfd, F_SETFL, flags); } errno = save_errno; return ret; }
int tls_bio(int fd, int timeout, TLS_SESS_STATE *TLScontext, int (*hsfunc) (SSL *), int (*rfunc) (SSL *, void *, int), int (*wfunc) (SSL *, const void *, int), void *buf, int num) { const char *myname = "tls_bio"; int status; int err; int enable_deadline; struct timeval time_left; /* amount of time left */ struct timeval time_deadline; /* time of deadline */ struct timeval time_now; /* time after SSL_mumble() call */ /* * Compensation for interface mis-match: With VSTREAMs, timeout <= 0 * means wait forever; with the read/write_wait() calls below, we need to * specify timeout < 0 instead. * * Safety: no time limit means no deadline. */ if (timeout <= 0) { timeout = -1; enable_deadline = 0; } /* * Deadline management is simpler than with VSTREAMs, because we don't * need to decrement a per-stream time limit. We just work within the * budget that is available for this tls_bio() call. */ else { enable_deadline = vstream_fstat(TLScontext->stream, VSTREAM_FLAG_DEADLINE); if (enable_deadline) { GETTIMEOFDAY(&time_deadline); time_deadline.tv_sec += timeout; } } /* * If necessary, retry the SSL handshake or read/write operation after * handling any pending network I/O. */ for (;;) { if (hsfunc) status = hsfunc(TLScontext->con); else if (rfunc) status = rfunc(TLScontext->con, buf, num); else if (wfunc) status = wfunc(TLScontext->con, buf, num); else msg_panic("%s: nothing to do here", myname); err = SSL_get_error(TLScontext->con, status); #if (OPENSSL_VERSION_NUMBER <= 0x0090581fL) /* * There is a bug up to and including OpenSSL-0.9.5a: if an error * occurs while checking the peers certificate due to some * certificate error (e.g. as happend with a RSA-padding error), the * error is put onto the error stack. If verification is not * enforced, this error should be ignored, but the error-queue is not * cleared, so we can find this error here. The bug has been fixed on * May 28, 2000. * * This bug so far has only manifested as 4800:error:0407006A:rsa * routines:RSA_padding_check_PKCS1_type_1:block type is not * 01:rsa_pk1.c:100: 4800:error:04067072:rsa * routines:RSA_EAY_PUBLIC_DECRYPT:padding check * failed:rsa_eay.c:396: 4800:error:0D079006:asn1 encoding * routines:ASN1_verify:bad get asn1 object call:a_verify.c:109: so * that we specifically test for this error. We print the errors to * the logfile and automatically clear the error queue. Then we retry * to get another error code. We cannot do better, since we can only * retrieve the last entry of the error-queue without actually * cleaning it on the way. * * This workaround is secure, as verify_result is set to "failed" * anyway. */ if (err == SSL_ERROR_SSL) { if (ERR_peek_error() == 0x0407006AL) { tls_print_errors(); msg_info("OpenSSL <= 0.9.5a workaround called: certificate errors ignored"); err = SSL_get_error(TLScontext->con, status); } } #endif /* * Correspondence between SSL_ERROR_* error codes and tls_bio_(read, * write, accept, connect, shutdown) return values (for brevity: * retval). * * SSL_ERROR_NONE corresponds with retval > 0. With SSL_(read, write) * this is the number of plaintext bytes sent or received. With * SSL_(accept, connect, shutdown) this means that the operation was * completed successfully. * * SSL_ERROR_WANT_(WRITE, READ) start a new loop iteration, or force * (retval = -1, errno = ETIMEDOUT) when the time limit is exceeded. * * All other SSL_ERROR_* cases correspond with retval <= 0. With * SSL_(read, write, accept, connect) retval == 0 means that the * remote party either closed the network connection or that it * requested TLS shutdown; with SSL_shutdown() retval == 0 means that * our own shutdown request is in progress. With all operations * retval < 0 means that there was an error. In the latter case, * SSL_ERROR_SYSCALL means that error details are returned via the * errno value. * * Find out if we must retry the operation and/or if there is pending * network I/O. * * XXX If we're the first to invoke SSL_shutdown(), then the operation * isn't really complete when the call returns. We could hide that * anomaly here and repeat the call. */ switch (err) { case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: if (enable_deadline) { GETTIMEOFDAY(&time_now); timersub(&time_deadline, &time_now, &time_left); timeout = time_left.tv_sec + (time_left.tv_usec > 0); if (timeout <= 0) { errno = ETIMEDOUT; return (-1); } } if (err == SSL_ERROR_WANT_WRITE) { if (write_wait(fd, timeout) < 0) return (-1); /* timeout error */ } else { if (read_wait(fd, timeout) < 0) return (-1); /* timeout error */ } break; /* * Unhandled cases: SSL_ERROR_WANT_(ACCEPT, CONNECT, X509_LOOKUP) * etc. Historically, Postfix silently treated these as ordinary * I/O errors so we don't really know how common they are. For * now, we just log a warning. */ default: msg_warn("%s: unexpected SSL_ERROR code %d", myname, err); /* FALLTHROUGH */ /* * With tls_timed_read() and tls_timed_write() the caller is the * VSTREAM library module which is unaware of TLS, so we log the * TLS error stack here. In a better world, each VSTREAM I/O * object would provide an error reporting method in addition to * the timed_read and timed_write methods, so that we would not * need to have ad-hoc code like this. */ case SSL_ERROR_SSL: if (rfunc || wfunc) tls_print_errors(); /* FALLTHROUGH */ case SSL_ERROR_ZERO_RETURN: case SSL_ERROR_NONE: errno = 0; /* avoid bogus warnings */ /* FALLTHROUGH */ case SSL_ERROR_SYSCALL: return (status); } } }