------------------------------------------------------------ revno: 12390 revision-id: squid3@treenet.co.nz-20121118113644-eu5asi2e0pwiwqh5 parent: squid3@treenet.co.nz-20121118113538-34a01mza98iau1c6 committer: Amos Jeffries branch nick: 3.3 timestamp: Sun 2012-11-18 04:36:44 -0700 message: basic_radius_auth: Fix several issues * abort on failed fcntl() non-blocking socket setup * retry send() on failure. Up to retry attempt count. Display send() errors to cache.log. * prevent buffer overflow on long command line arguments. * make compiler buffer overflow checks happier with RADIUS packet creation code. Detected by Coverity Scan. Issues 740314, 740315, 740410, 740474, 743276 ------------------------------------------------------------ # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: squid3@treenet.co.nz-20121118113644-eu5asi2e0pwiwqh5 # target_branch: http://bzr.squid-cache.org/bzr/squid3/3.3 # testament_sha1: 4cb714c248b0110cd983e732e8860d01003709bb # timestamp: 2012-11-18 11:39:23 +0000 # source_branch: http://bzr.squid-cache.org/bzr/squid3/3.3 # base_revision_id: squid3@treenet.co.nz-20121118113538-\ # 34a01mza98iau1c6 # # Begin patch === modified file 'helpers/basic_auth/RADIUS/basic_radius_auth.cc' --- helpers/basic_auth/RADIUS/basic_radius_auth.cc 2012-08-29 13:51:52 +0000 +++ helpers/basic_auth/RADIUS/basic_radius_auth.cc 2012-11-18 11:36:44 +0000 @@ -321,7 +321,7 @@ length = MAXPWNAM; } *ptr = length + 2; - ++ptr; + ptr = (unsigned char*)send_buffer + sizeof(AUTH_HDR); memcpy(ptr, username, length); ptr += length; total_length += length + 2; @@ -424,7 +424,13 @@ * Send the request we've built. */ gettimeofday(&sent, NULL); - send(socket_fd, (char *) auth, total_length, 0); + if (send(socket_fd, (char *) auth, total_length, 0) < 0) { + // EAGAIN is expected at high traffic, just retry + // TODO: block/sleep a few ms to let the apparently full buffer drain ? + if (errno != EAGAIN && errno != EWOULDBLOCK) + fprintf(stderr,"ERROR: RADIUS send() failure: %s\n", xstrerror()); + continue; + } while ((time_spent = time_since(&sent)) < 1000000) { struct timeval tv; int rc, len; @@ -488,16 +494,20 @@ cfname = optarg; break; case 'h': - strcpy(server, optarg); + strncpy(server, optarg, sizeof(server)-1); + server[sizeof(server)-1] = '\0'; break; case 'p': - strcpy(svc_name, optarg); + strncpy(svc_name, optarg, sizeof(svc_name)-1); + svc_name[sizeof(svc_name)-1] = '\0'; break; case 'w': - strcpy(secretkey, optarg); + strncpy(secretkey, optarg, sizeof(secretkey)-1); + secretkey[sizeof(secretkey)-1] = '\0'; break; case 'i': - strcpy(identifier, optarg); + strncpy(identifier, optarg, sizeof(identifier)-1); + identifier[sizeof(identifier)-1] = '\0'; break; case 't': retries = atoi(optarg); @@ -565,7 +575,10 @@ exit(1); } #ifdef O_NONBLOCK - fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK); + if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK) < 0) { + fprintf(stderr,"%s| ERROR: fcntl() failure: %s\n", argv[0], xstrerror()); + exit(1); + } #endif nas_ipaddr = ntohl(salocal.sin_addr.s_addr); while (fgets(buf, HELPER_INPUT_BUFFER, stdin) != NULL) {