예제 #1
0
void _mark_thread_safe(int start_or_stop, int dologging, const char* descrip, 
					   const char* func, const char* file, int line)
{
	mark_thread_func_t callback=0;
	const char* mode=0;
#ifdef WIN32
	char buf[40];
#endif

	switch (start_or_stop) {
		case 1:
			callback = start_callback;
			mode = "start";
			break;
		case 2:
			callback = stop_callback;
			mode = "stop";
			break;
		default:
			EXCEPT("unexpected mode: %d",start_or_stop);
	}

	if ( !callback ) {
		// nothing to do, we're done.
		return;
	}

	if (descrip == NULL) {
		descrip = "\0";
	}

#ifdef WIN32	
	strcpy(buf,"tid=");
	func = itoa(GetCurrentThreadId(), &buf[4], 10 );	
#endif

	if ( dologging && IsDebugVerbose(D_THREADS)) {
		dprintf(D_THREADS,"Entering thread safe %s [%s] in %s:%d %s()\n",
				mode, descrip, my_local_basename(file), line, func);
	}

	(*callback)();

	if ( dologging && IsDebugVerbose(D_THREADS)) {
		dprintf(D_THREADS,"Leaving thread safe %s [%s] in %s:%d %s()\n",
				mode, descrip, my_local_basename(file), line, func);
	}

	return;
}
예제 #2
0
int Condor_Auth_Kerberos :: map_domain_name(const char * domain)
{
    if (RealmMap == 0) {
        init_realm_mapping();
        // it's okay if it returns false
    }

    // two cases, if domain is the same as the current uid domain,
    // then we are okay, other wise, see if we have a map
    if (RealmMap) {
        MyString from(domain), to;
        if (RealmMap->lookup(from, to) != -1) {
			if (IsFulldebug(D_SECURITY)) {
				dprintf (D_SECURITY, "KERBEROS: mapping realm %s to domain %s.\n", 
					from.Value(), to.Value());
			}
            setRemoteDomain(to.Value());
            return TRUE;
        } else {
			// if the map exists, they must be listed.  and they're NOT!
			return FALSE;
		}
    }

    // if there is no map, we just allow realm -> domain.
	if (IsDebugVerbose(D_SECURITY)) {
		dprintf (D_SECURITY, "KERBEROS: mapping realm %s to domain %s.\n", 
			domain, domain);
		setRemoteDomain(domain);
	}
	return TRUE;

}
예제 #3
0
/* Get the next n bytes from the message:
 * Copy the next 'size' bytes of the message to 'dta'
 * param: dta - buffer to which data will be copied
 *        size - the number of bytes to be copied
 * return: the actual number of bytes copied, if success
 *         -1, if failed
 * Notice: dta must be a pointer to object(>= size)
 */
int _condorInMsg::getn(char* dta, const int size)
{
	int len, total = 0;

	if(!dta || passed + size > msgLen) {
        dprintf(D_NETWORK, "dta is NULL or more data than queued is requested\n");
		return -1;
    }

	while(total != size) {
		len = size - total;
		if(len > curDir->dEntry[curPacket].dLen - curData)
			len = curDir->dEntry[curPacket].dLen - curData;
		memcpy(&dta[total],
		       &(curDir->dEntry[curPacket].dGram[curData]), len);
		total += len;
		incrementCurData(len);
	} // of while(total..)

    if( IsDebugVerbose(D_NETWORK) ) {
        dprintf(D_NETWORK, "%d bytes read from UDP[size=%ld, passed=%d]\n",
                total, msgLen, passed);
    }
	return total;
}
예제 #4
0
bool
VMStarterInfo::updateUsageOfVM(void)
{
	if( m_vm_pid == 0) {
		return false;
	}

	int proc_status = PROCAPI_OK;

	piPTR pi = NULL;
	if( ProcAPI::getProcInfo(m_vm_pid, pi, proc_status) == 
			PROCAPI_SUCCESS ) {
		memcpy(&m_vm_alive_pinfo, pi, sizeof(struct procInfo));
		if( IsDebugVerbose(D_LOAD) ) {
			dprintf(D_LOAD,"Usage of process[%d] for a VM is updated\n", 
					m_vm_pid);
			dprintf(D_LOAD,"sys_time=%lu, user_time=%lu, image_size=%lu\n", 
					pi->sys_time, pi->user_time, get_image_size(*pi));
		}
		delete pi;
		return true;
	}
	if (pi) delete pi;
	return false;
}
예제 #5
0
float
sysapi_load_avg_raw(void)
{

	float first, second, third;
	int mib[4];
	struct loadavg load;
	size_t len;

	sysapi_internal_reconfig();

	mib[0] = CTL_VM;
	mib[1] = VM_LOADAVG;
	len = sizeof(struct loadavg);		
	sysctl(mib, 2, &load, &len, NULL, 0);
	first = (float)load.ldavg[0] / (float)load.fscale;
	second = (float)load.ldavg[1] / (float)load.fscale;
	third = (float)load.ldavg[2] / (float)load.fscale;

	if( IsDebugVerbose( D_LOAD ) ) {
		dprintf( D_LOAD, "Load avg: %.2f %.2f %.2f\n", 
			first, second, third );
	}
	return first;
}
예제 #6
0
float
sysapi_load_avg_raw(void)
{

	float val;

	sysapi_internal_reconfig();
	val = lookup_load_avg_via_uptime();

	if( IsDebugVerbose( D_LOAD ) ) {
		dprintf( D_LOAD, "Load avg: %.2f\n", val );
	}
	return val;
}
예제 #7
0
float
sysapi_load_avg_raw(void)
{
    FILE	*proc;
	struct utsname buf;
	int		major, minor, patch;
	float	short_avg, medium_avg, long_avg;

	sysapi_internal_reconfig();

	// Obtain the kernel version so that we know what /proc looks like..
	if( uname(&buf) < 0 )  return -1;
	sscanf(buf.release, "%d.%d.%d", &major, &minor, &patch);

	// /proc/loadavg looks like:

	// Kernel Version 2.0.0:
	// 0.03 0.03 0.09 2/42 15582

    proc=safe_fopen_wrapper_follow("/proc/loadavg","r",0644);
    if(!proc)
	return -1;

	switch(major) {
		case 1:
		case 2:
		case 3:
    		if (fscanf(proc, "%f %f %f", &short_avg, &medium_avg, &long_avg) != 3) {
				dprintf(D_ALWAYS, "Failed to fscanf 3 floats from /proc/loadavg\n");
				fclose(proc);
				return -1;
			}
			break;

		default:
			dprintf(D_ALWAYS, "/proc format unknown for kernel version %d.%d.%d\n",
				major, minor, patch);
    		fclose(proc);
			return -1;
			break;
	}

    fclose(proc);

	if( IsDebugVerbose( D_LOAD ) ) {
		dprintf( D_LOAD, "Load avg: %.2f %.2f %.2f\n", short_avg, 
				 medium_avg, long_avg );
	}
	return short_avg;
}
예제 #8
0
파일: Starter.cpp 프로젝트: emaste/htcondor
float
Starter::percentCpuUsage( void )
{
	if (daemonCore->Get_Family_Usage(s_pid, s_usage, true) == FALSE) {
		EXCEPT( "Starter::percentCpuUsage(): Fatal error getting process "
		        "info for the starter and decendents" ); 
	}

	// In vm universe, there may be a process dealing with a VM.
	// Unfortunately, such a process is created by a specific 
	// running daemon for virtual machine program(such as vmware-serverd).
	// So our Get_Family_Usage is unable to get usage for the process.
	// Here, we call a function in vm universe manager.
	// If this starter is for vm universe, s_usage will be updated.
	// Otherwise, s_usage will not change.
	if ( resmgr ) {
		resmgr->m_vmuniverse_mgr.getUsageForVM(s_pid, s_usage);
		
		// Now try to tack on details posted in the job ad because 
		// hypervisors such as libvirt will spawn processes outside 
		// of condor's perview. 
		float fPercentCPU=0.0;
		int iNumCPUs=0;
		ClassAd * jobAd = s_claim->ad();
		
		jobAd->LookupFloat(ATTR_JOB_VM_CPU_UTILIZATION, fPercentCPU);
		jobAd->LookupInteger(ATTR_JOB_VM_VCPUS, iNumCPUs);
		
		// computations outside take cores into account.
		fPercentCPU = fPercentCPU * iNumCPUs;
		
		dprintf( D_LOAD, "Starter::percentCpuUsage() adding VM Utilization %f\n",fPercentCPU);
		
		s_usage.percent_cpu += fPercentCPU;
		
	}

	if( IsDebugVerbose(D_LOAD) ) {
		dprintf(D_LOAD,
		        "Starter::percentCpuUsage(): Percent CPU usage "
		        "for the family of starter with pid %u is: %f\n",
		        s_pid,
		        s_usage.percent_cpu );
	}

	return s_usage.percent_cpu;
}
예제 #9
0
void
VMStarterInfo::getUsageOfVM(ProcFamilyUsage &usage)
{
	bool updated = updateUsageOfVM();

	usage.user_cpu_time = m_vm_exited_pinfo.user_time + m_vm_alive_pinfo.user_time;
	usage.sys_cpu_time = m_vm_exited_pinfo.sys_time + m_vm_alive_pinfo.sys_time;

	if( updated ) {
		usage.percent_cpu = m_vm_alive_pinfo.cpuusage;
	}else
		usage.percent_cpu = 0;

	unsigned long exited_max_image = get_image_size(m_vm_exited_pinfo);
	unsigned long alive_max_image = get_image_size(m_vm_alive_pinfo);

	usage.max_image_size = (exited_max_image > alive_max_image ) ? 
				exited_max_image : alive_max_image;

	if( updated ) {
		usage.total_image_size = m_vm_alive_pinfo.imgsize;
		usage.total_resident_set_size = m_vm_alive_pinfo.rssize;
#if HAVE_PSS
		usage.total_proportional_set_size = m_vm_alive_pinfo.pssize;
		usage.total_proportional_set_size = m_vm_alive_pinfo.pssize_available;
#endif
	}else {
		usage.total_image_size = 0;
        usage.total_resident_set_size = 0;
#if HAVE_PSS
		usage.total_proportional_set_size = 0;
		usage.total_proportional_set_size = false;
#endif
	}

	if( IsDebugVerbose(D_LOAD) ) {
		dprintf( D_LOAD,
				"VMStarterInfo::getUsageOfVM(): Percent CPU usage "
				"for VM process with pid %u is: %f\n",
				m_vm_pid,
				usage.percent_cpu );
	}
}
예제 #10
0
int Authentication::authenticate_inner( char *hostAddr, const char* auth_methods,
		CondorError* errstack, int timeout, bool non_blocking)
{
#if defined(SKIP_AUTHENTICATION)
	dprintf(D_ALWAYS, "Skipping....\n");
	/*
	errstack->push ( "AUTHENTICATE", AUTHENTICATE_ERR_NOT_BUILT,
			"this condor was built with SKIP_AUTHENTICATION");
	*/
	return 0;
#else
	m_host_addr = hostAddr ? hostAddr : "(unknown)";
	if (timeout > 0) {
		dprintf( D_SECURITY, "AUTHENTICATE: setting timeout for %s to %d.\n", m_host_addr.c_str(), timeout);
		m_auth_timeout_time = time(0) + timeout;
	} else {
		m_auth_timeout_time = 0;
	}

	if (IsDebugVerbose(D_SECURITY)) {
		if (m_host_addr.size()) {
			dprintf ( D_SECURITY, "AUTHENTICATE: in authenticate( addr == '%s', "
					"methods == '%s')\n", m_host_addr.c_str(), auth_methods);
		} else {
			dprintf ( D_SECURITY, "AUTHENTICATE: in authenticate( addr == NULL, "
					"methods == '%s')\n", auth_methods);
		}
	}

	m_methods_to_try = auth_methods;

	m_continue_handshake = false;
	m_continue_auth = false;
	auth_status = CAUTH_NONE;
	method_used = NULL;
	m_auth = NULL;

	return authenticate_continue(errstack, non_blocking);
#endif
}
예제 #11
0
bool _condorPacket :: set_encryption_id(const char * keyId)
{
    // This should be for outpacket only!
    ASSERT(empty());
    if (outgoingEncKeyId_) {
        if( curIndex > 0 ) {
            curIndex -= outgoingEidLen_;
            if (curIndex == SAFE_MSG_CRYPTO_HEADER_SIZE) {
                    // empty header
                curIndex -= SAFE_MSG_CRYPTO_HEADER_SIZE;
            }
            ASSERT( curIndex >= 0 );
        }

        free(outgoingEncKeyId_);
        outgoingEncKeyId_ = 0;
        outgoingEidLen_   = 0;
    }
    
    if (keyId) {
        outgoingEncKeyId_ = strdup(keyId);
        outgoingEidLen_   = strlen(outgoingEncKeyId_);
		if( IsDebugVerbose(D_SECURITY) ) {
			dprintf( D_SECURITY, 
					 "set_encryption_id: setting key length %d\n", 
					 outgoingEidLen_ );  
		}
        if ( curIndex == 0 ) {
            curIndex += SAFE_MSG_CRYPTO_HEADER_SIZE;
        }
        curIndex += outgoingEidLen_;
    }

    length = curIndex;

    return true;
}
예제 #12
0
/*
   this function must return the same values as globus!!!!

   also, it must allocate memory the same:  create a new string and
   write address into '*to'.
 
*/
int Condor_Auth_X509::condor_gss_assist_gridmap(const char * from, char ** to) {

	if (GridMap == 0) {
		ParseMapFile();
	}

	if (GridMap) {
		MyString f(from), t;
		if (GridMap->lookup(f, t) != -1) {
			if (IsDebugVerbose(D_SECURITY)) {
				dprintf (D_SECURITY, "GSI: subject %s is mapped to user %s.\n", 
					f.Value(), t.Value());
			}

			*to = strdup(t.Value());
			return GSS_S_COMPLETE;
		} else {
			// if the map exists, they must be listed.  and they're NOT!
			return !GSS_S_COMPLETE;
		}
	}

	return !GSS_S_COMPLETE;
}
예제 #13
0
/* Generic read/write wrappers for condor.  These function emulate-ish the 
 * read/write system calls under unix except that they are portable, use
 * a timeout, and make sure that all data is read or written.
 *
 * A few notes on the behavior differing from POSIX:
 * - These will never fail due to EINTR.
 * - If in non_blocking mode, there may be a short read or write returned.
 * - The corresponding POSIX functon returns 0 bytes read when the peer closed
 *   the socket; these return -2.
 * - If zero bytes were read/written in non-blocking mode, this will return 0.  This differs
 *   from POSIX.
 * - Providing a zero-sized argument to this function will cause the program to abort().
 *
 * Returns < 0 on failure.  -1 = general error, -2 = peer closed socket
 */
int
condor_read( char const *peer_description, SOCKET fd, char *buf, int sz, int timeout, int flags, bool non_blocking )
{
	Selector selector;
	int nr = 0, nro;
	unsigned int start_time=0, cur_time=0;
	char sinbuf[SINFUL_STRING_BUF_SIZE];

	if( IsDebugLevel(D_NETWORK) ) {
		dprintf(D_NETWORK,
				"condor_read(fd=%d %s,,size=%d,timeout=%d,flags=%d,non_blocking=%d)\n",
				fd,
				not_null_peer_description(peer_description,fd,sinbuf),
				sz,
				timeout,
				flags,
				non_blocking);
	}

	/* PRE Conditions. */
	ASSERT(fd >= 0);     /* Need valid file descriptor */
	ASSERT(buf != NULL); /* Need real memory to put data into */
	ASSERT(sz > 0);      /* Need legit size on buffer */

	if (non_blocking) {
#ifdef WIN32
		unsigned long mode = 1; // nonblocking mode
		if (ioctlsocket(fd, FIONBIO, &mode) < 0)
			return -1;
#else
		int fcntl_flags;
		if ( (fcntl_flags=fcntl(fd, F_GETFL)) < 0 )
			return -1;
			// set nonblocking mode
		if ( ((fcntl_flags & O_NONBLOCK) == 0) && fcntl(fd, F_SETFL, fcntl_flags | O_NONBLOCK) == -1 )
			return -1;
#endif
		nr = -2;
		while (nr == -2 || (nr == -1 && errno == EINTR)) {
			nr = recv(fd, buf, sz, flags);
		}

		if ( nr <= 0 ) {
			int the_error;
			char const *the_errorstr;
#ifdef WIN32
			the_error = WSAGetLastError();
			the_errorstr = "";
#else
			the_error = errno;
			the_errorstr = strerror(the_error);
#endif
			if ( nr == 0 && !(flags & MSG_PEEK)) {
				nr = -2;
				dprintf( D_FULLDEBUG, "condor_read(): "
					"Socket closed when trying to read %d bytes from %s in non-blocking mode\n",
					sz,
					not_null_peer_description(peer_description,fd,sinbuf) );
			} else if ( !errno_is_temporary(the_error) ) {
				dprintf( D_ALWAYS, "condor_read() failed: recv() %d bytes from %s "
					"returned %d, "     
					"timeout=%d, errno=%d %s.\n",
					sz,                 
					not_null_peer_description(peer_description,fd,sinbuf),
					nr, timeout, the_error, the_errorstr );
			}
			else
			{
				nr = 0;
			}
		}

#ifdef WIN32
		mode = 0; // reset blocking mode
		if (ioctlsocket(fd, FIONBIO, &mode) < 0)
			return -1;
#else
			// reset flags to prior value
		if ( ((fcntl_flags & O_NONBLOCK) == 0) && (fcntl(fd, F_SETFL, fcntl_flags) == -1) )
			return -1;
#endif
		return nr;
	}

	selector.add_fd( fd, Selector::IO_READ );
	
	if ( timeout > 0 ) {
		start_time = time(NULL);
		cur_time = start_time;
	}

	while( nr < sz ) {

		if( timeout > 0 ) {

			if( cur_time == 0 ) {
				cur_time = time(NULL);
			}

			// If it hasn't yet been longer then we said we would wait...
			if( start_time + timeout > cur_time ) {
				selector.set_timeout( (start_time + timeout) - cur_time );
			} else {
				dprintf( D_ALWAYS, 
						 "condor_read(): timeout reading %d bytes from %s.\n",
						 sz,
						 not_null_peer_description(peer_description,fd,sinbuf) );
				return -1;
			}
			
			cur_time = 0;

			if( IsDebugVerbose( D_NETWORK ) ) {
				dprintf(D_NETWORK, "condor_read(): fd=%d\n", fd);
			}
			selector.execute();
			if( IsDebugVerbose( D_NETWORK ) ) {
				dprintf(D_NETWORK, "condor_read(): select returned %d\n", 
						selector.select_retval());
			}

			if ( selector.timed_out() ) {
				dprintf( D_ALWAYS, 
						 "condor_read(): timeout reading %d bytes from %s.\n",
						 sz,
						 not_null_peer_description(peer_description,fd,sinbuf) );
				return -1;

			} else if ( selector.signalled() ) {
				continue;
			} else if ( !selector.has_ready() ) {
				int the_error;
                char const *the_errorstr;
#ifdef WIN32
				the_error = WSAGetLastError();
                the_errorstr = "";
#else
				the_error = errno;
                the_errorstr = strerror(the_error);
#endif

				dprintf( D_ALWAYS, "condor_read() failed: select() "
						 "returns %d, reading %d bytes from %s (errno=%d %s).\n",
						 selector.select_retval(),
						 sz,
						 not_null_peer_description(peer_description,fd,sinbuf),
						 the_error, the_errorstr );
				return -1;
			}
		}
		
		start_thread_safe("recv");

		nro = recv(fd, &buf[nr], sz - nr, flags);
		// Save the error value before stop_thread_safe(), as that may
		// overwrite it.
		int the_error;
#ifdef WIN32
		the_error = WSAGetLastError();
#else
		the_error = errno;
#endif

		stop_thread_safe("recv");

		if( nro <= 0 ) {

				// If timeout > 0, and we made it here, then
				// we know we were woken by select().  Now, if
				// select() wakes up on a read fd, and then recv() 
				// subsequently returns 0, that means that the
				// socket has been closed by our peer.
				// If timeout == 0, then recv() should have 
				// blocked until 1 or more bytes arrived.
				// Thus no matter what, if nro==0, then the
				// socket must be closed.
			if ( nro == 0 ) {
				dprintf( D_FULLDEBUG, "condor_read(): "
						 "Socket closed when trying to read %d bytes from %s\n",
						 sz,
						 not_null_peer_description(peer_description,fd,sinbuf) );
				return -2;
			}

            char const *the_errorstr;
#ifdef WIN32
            the_errorstr = "";
#else
            the_errorstr = strerror(the_error);
#endif
			if ( errno_is_temporary(the_error) ) {
				dprintf( D_FULLDEBUG, "condor_read(): "
				         "recv() returned temporary error %d %s,"
				         "still trying to read from %s\n",
				         the_error,the_errorstr,
				         not_null_peer_description(peer_description,fd,sinbuf) );
				continue;
			}

			dprintf( D_ALWAYS, "condor_read() failed: recv(fd=%d) returned %d, "
					 "errno = %d %s, reading %d bytes from %s.\n",
					 fd, nro, the_error, the_errorstr, sz,
					 not_null_peer_description(peer_description,fd,sinbuf) );

			if( the_error == ETIMEDOUT ) {
				if( timeout <= 0 ) {
					dprintf( D_ALWAYS,
							 "condor_read(): read timeout during blocking read from %s\n",
							 not_null_peer_description(peer_description,fd,sinbuf));
				}
				else {
					int lapse = (int)(time(NULL)-start_time);
					dprintf( D_ALWAYS,
							 "condor_read(): UNEXPECTED read timeout after %ds during non-blocking read from %s (desired timeout=%ds)\n",
							 lapse,
							 not_null_peer_description(peer_description,fd,sinbuf),
							 timeout);
				}
			}
			return -1;
		}
		nr += nro;
	}
	
/* Post Conditions */
	ASSERT( nr == sz );  // we should have read *ALL* the data
	return nr;
}
예제 #14
0
/* Get data from message up to the delimeter:
 * Copy data of the message to 'dta', starting from current position up to meeting 'delim'
 *	@param: buf - buffer to which data will be copied
 *	        delim - the delimeter
 *	@return: the number of bytes copied, if success
 *	         -1, if failed
 *
 * Notice: new character array will be allocated as needed and the space will be
 *         deallocated at the time of the next call of this method, so 'buf' must be
 *         a pointer to nothing and must not be deleted by caller
 */
int _condorInMsg::getPtr(void *&buf, char delim)
{
	_condorDirPage *tempDir;
	int tempPkt, tempData;
	size_t n = 1;
	int size;

	tempDir = curDir;
	tempPkt = curPacket;
	tempData = curData;

	bool copy_needed = false;
	while(1) {
		char *msgbuf = &tempDir->dEntry[tempPkt].dGram[tempData];
		size_t msgbufsize = tempDir->dEntry[tempPkt].dLen - tempData;
		char *delim_ptr = (char *)memchr(msgbuf,delim,msgbufsize);

		if( delim_ptr ) {
			n += delim_ptr - msgbuf;
			if( n == msgbufsize ) {
					// Need to copy the data in this case, because when
					// buffer is consumed by incrementCurData(), it will
					// be freed.
				copy_needed = true;
			}
			if( !copy_needed ) {
					// Special (common) case: the whole string is in one piece
					// so just return a pointer to it and skip the drudgery
					// of copying the bytes into another buffer.
				incrementCurData(n);
				buf = msgbuf;
				return n;
			}
			break; // found delim
		}
		copy_needed = true; // string spans multiple buffers

		n += msgbufsize;
		tempPkt++;
		tempData = 0;
		if(tempPkt >= SAFE_MSG_NO_OF_DIR_ENTRY) {
			if(!tempDir->nextDir) {
				return -1;
			}
			tempDir = tempDir->nextDir;
			tempPkt = 0;
		} else if(!tempDir->dEntry[tempPkt].dGram) { // was the last packet
			if( IsDebugVerbose(D_NETWORK) )
				dprintf(D_NETWORK,
				        "SafeMsg::getPtr: get to end & '%c' not found\n", delim);
			return -1;
		}
	}

	if( IsDebugVerbose(D_NETWORK) )
		dprintf(D_NETWORK, "SafeMsg::_longMsg::getPtr: found delim = %c & length = %lu\n",
			  delim, (unsigned long)n);
	if( n > tempBufLen ) {
		if(tempBuf) {
			free(tempBuf);
		}
		tempBuf = (char *)malloc(n);
		if(!tempBuf) {
			dprintf(D_ALWAYS, "getPtr, fail at malloc(%lu)\n", (unsigned long)n);
			tempBufLen = 0;
			return -1;
		}
		tempBufLen = n;
	}
	size = getn(tempBuf, n);
	buf = tempBuf;
	//cout << "\t\tInMsg::getPtr: " << (char *)buf << endl;
	return size;
}
예제 #15
0
int Authentication::authenticate_continue( CondorError* errstack, bool non_blocking )
{
	// Check for continuations;
	int firm = -1;
	bool do_handshake = true;
	if (m_continue_handshake) {
		firm = handshake_continue(m_methods_to_try, non_blocking);
		if ( firm == -2 ) {
			dprintf(D_SECURITY, "AUTHENTICATE: handshake would still block\n");
			return 2;
		}
		m_continue_handshake = false;
		do_handshake = false;
	}

	int auth_rc = 0;
	bool do_authenticate = true;
	if (m_continue_auth) {
		auth_rc = m_auth->authenticate_continue(errstack, non_blocking);
		if (auth_rc == 2 ) {
			dprintf(D_SECURITY, "AUTHENTICATE: auth would still block\n");
			return 2;
		}
		m_continue_auth = false;
		do_authenticate = false;
		goto authenticate;
	}
 
	m_auth = NULL;
	while (auth_status == CAUTH_NONE ) {
		if (m_auth_timeout_time>0 && m_auth_timeout_time <= time(0)) {
			dprintf(D_SECURITY, "AUTHENTICATE: exceeded deadline %ld\n", m_auth_timeout_time);
			errstack->pushf( "AUTHENTICATE", AUTHENTICATE_ERR_TIMEOUT, "exceeded %ld deadline during authentication", m_auth_timeout_time );
			break;
		}
		if (IsDebugVerbose(D_SECURITY)) {
			dprintf(D_SECURITY, "AUTHENTICATE: can still try these methods: %s\n", m_methods_to_try.c_str());
		}

		if (do_handshake) {
			firm = handshake(m_methods_to_try, non_blocking);
		}
		do_handshake = true;

		if ( firm == -2 ) {
			dprintf(D_SECURITY, "AUTHENTICATE: handshake would block\n");
			m_continue_handshake = true;
			return 2;
		}
		if ( firm < 0 ) {
			dprintf(D_ALWAYS, "AUTHENTICATE: handshake failed!\n");
			errstack->push( "AUTHENTICATE", AUTHENTICATE_ERR_HANDSHAKE_FAILED, "Failure performing handshake" );
			break;
		}

		m_method_name = "";
		switch ( firm ) {
#if defined(HAVE_EXT_GLOBUS)
			case CAUTH_GSI:
				m_auth = new Condor_Auth_X509(mySock);
				m_method_name = "GSI";
				break;
#endif /* HAVE_EXT_GLOBUS */

#ifdef HAVE_EXT_OPENSSL
			case CAUTH_SSL:
				m_auth = new Condor_Auth_SSL(mySock);
				m_method_name = "SSL";
				break;
#endif

#if defined(HAVE_EXT_KRB5) 
			case CAUTH_KERBEROS:
				m_auth = new Condor_Auth_Kerberos(mySock);
				m_method_name = "KERBEROS";
				break;
#endif

#ifdef HAVE_EXT_OPENSSL  // 3DES is the prequisite for passwd auth
			case CAUTH_PASSWORD:
				m_auth = new Condor_Auth_Passwd(mySock);
				m_method_name = "PASSWORD";
				break;
#endif
 
#if defined(WIN32)
			case CAUTH_NTSSPI:
				m_auth = new Condor_Auth_SSPI(mySock);
				m_method_name = "NTSSPI";
				break;
#else
			case CAUTH_FILESYSTEM:
				m_auth = new Condor_Auth_FS(mySock);
				m_method_name = "FS";
				break;
			case CAUTH_FILESYSTEM_REMOTE:
				m_auth = new Condor_Auth_FS(mySock, 1);
				m_method_name = "FS_REMOTE";
				break;
#endif /* !defined(WIN32) */
			case CAUTH_CLAIMTOBE:
				m_auth = new Condor_Auth_Claim(mySock);
				m_method_name = "CLAIMTOBE";
				break;
 
			case CAUTH_ANONYMOUS:
				m_auth = new Condor_Auth_Anonymous(mySock);
				m_method_name = "ANONYMOUS";
				break;
 
			case CAUTH_NONE:
				dprintf(D_SECURITY|D_FULLDEBUG,"AUTHENTICATE: no available authentication methods succeeded!\n");
				errstack->push("AUTHENTICATE", AUTHENTICATE_ERR_OUT_OF_METHODS,
						"Failed to authenticate with any method");
				return 0;

			default:
				dprintf(D_ALWAYS,"AUTHENTICATE: unsupported method: %i, failing.\n", firm);
				errstack->pushf("AUTHENTICATE", AUTHENTICATE_ERR_OUT_OF_METHODS,
						"Failure.  Unsupported method: %i", firm);
				return 0;
		}


		if (IsDebugVerbose(D_SECURITY)) {
			dprintf(D_SECURITY, "AUTHENTICATE: will try to use %d (%s)\n", firm,
					(m_method_name.size()?m_method_name.c_str():"?!?") );
		}

		// We have just picked a new method, so we definitely want to
		// make this value true.  We log a message only if we changed
		// it.
		if(!do_authenticate) {
			do_authenticate = true;
			if (IsDebugVerbose(D_SECURITY)) {
				dprintf(D_SECURITY, "AUTHENTICATE: forcing do_authenticate to true.\n");
			}
		}

		//------------------------------------------
		// Now authenticate
		//------------------------------------------
authenticate:
		// Re-check deadline as handshake could have taken awhile.
		if (m_auth_timeout_time>0 && m_auth_timeout_time <= time(0)) {
			dprintf(D_SECURITY, "AUTHENTICATE: exceeded deadline %ld\n", m_auth_timeout_time);
			errstack->pushf( "AUTHENTICATE", AUTHENTICATE_ERR_TIMEOUT, "exceeded %ld deadline during authentication", m_auth_timeout_time );
			break;
		}

		if (IsDebugVerbose(D_SECURITY)) {
			dprintf (D_SECURITY, "AUTHENTICATE: do_authenticate is %i.\n", do_authenticate);
		}

		if (do_authenticate) {
			auth_rc = m_auth->authenticate(m_host_addr.c_str(), errstack, non_blocking);
			if (auth_rc == 2) {
				m_continue_auth = true;
				return 2;
			}
		}

			// check to see if the auth IP is the same as the socket IP
		if( auth_rc ) {
			char const *sockip = mySock->peer_ip_str();
			char const *authip = m_auth->getRemoteHost() ;

			auth_rc = !sockip || !authip || !strcmp(sockip,authip);

			if (!auth_rc && !param_boolean( "DISABLE_AUTHENTICATION_IP_CHECK", false)) {
				errstack->pushf("AUTHENTICATE", AUTHENTICATE_ERR_METHOD_FAILED,
								"authenticated remote host does not match connection address (%s vs %s)", authip, sockip );
				dprintf (D_ALWAYS, "AUTHENTICATE: ERROR: authenticated remot ehost does not match connection address (%s vs %s); configure DISABLE_AUTHENTICATION_IP_CHECK=TRUE if this check should be skipped\n",authip,sockip);
			}
		}

		if( !auth_rc ) {
			delete m_auth;
			m_auth = NULL;

			errstack->pushf("AUTHENTICATE", AUTHENTICATE_ERR_METHOD_FAILED,
					"Failed to authenticate using %s", m_method_name.c_str() );

			//if authentication failed, try again after removing from client tries
			if ( mySock->isClient() ) {
				// need to remove this item from the MyString!!  perhaps there is a
				// better way to do this...  anyways, 'firm' is equal to the bit value
				// of a particular method, so we'll just convert each item in the list
				// and keep it if it's not that particular bit.
				StringList meth_iter( m_methods_to_try.c_str() );
				meth_iter.rewind();
				MyString new_list;
				char *tmp = NULL;
				while( (tmp = meth_iter.next()) ) {
					int that_bit = SecMan::getAuthBitmask( tmp );

					// keep if this isn't the failed method.
					if (firm != that_bit) {
						// and of course, keep the comma's correct.
						if (new_list.Length() > 0) {
							new_list += ",";
						}
						new_list += tmp;
					}
				}

				// trust the copy constructor. :)
				m_methods_to_try = new_list;
			}

			dprintf(D_SECURITY,"AUTHENTICATE: method %d (%s) failed.\n", firm,
					(m_method_name.size()?m_method_name.c_str():"?!?"));
		} else {
			// authentication succeeded.  store the object (we may call upon
			// its wrapper functions) and set the auth_status of this sock to
			// the bitmask method we used and the method_used to the string
			// name.  (string name is obtained above because there is currently
			// no bitmask -> string map)
			authenticator_ = m_auth;
			m_auth = NULL;
			auth_status = authenticator_->getMode();
			if (m_method_name.size()) {
				method_used = strdup(m_method_name.c_str());
			} else {
				method_used = NULL;
			}
		}
	}
	return authenticate_finish(errstack);
}
예제 #16
0
int Authentication::authenticate_finish(CondorError *errstack)
{
	//if none of the methods succeeded, we fall thru to default "none" from above
	int retval = ( auth_status != CAUTH_NONE );
	if (IsDebugVerbose(D_SECURITY)) {
		dprintf(D_SECURITY, "AUTHENTICATE: auth_status == %i (%s)\n", auth_status,
				(method_used?method_used:"?!?") );
	}
	dprintf(D_SECURITY, "Authentication was a %s.\n", retval == 1 ? "Success" : "FAILURE" );


	// at this point, all methods have set the raw authenticated name available
	// via getAuthenticatedName().

	if(authenticator_) {
		dprintf (D_SECURITY, "ZKM: setting default map to %s\n",
				 authenticator_->getRemoteFQU()?authenticator_->getRemoteFQU():"(null)");
	}

	// check to see if CERTIFICATE_MAPFILE was defined.  if so, use it.  if
	// not, do nothing.  the user and domain have been filled in by the
	// authentication method itself, so just leave that alone.
	char * cert_map_file = param("CERTIFICATE_MAPFILE");
	bool use_mapfile = (cert_map_file != NULL);
	if (cert_map_file) {
		free(cert_map_file);
		cert_map_file = 0;
	}

	// if successful so far, invoke the security MapFile.  the output of that
	// is the "canonical user".  if that has an '@' sign, split it up on the
	// last '@' and set the user and domain.  if there is more than one '@',
	// the user will contain the leftovers after the split and the domain
	// always has none.
	if (retval && use_mapfile) {
		const char * name_to_map = authenticator_->getAuthenticatedName();
		if (name_to_map) {
			dprintf (D_SECURITY, "ZKM: name to map is '%s'\n", name_to_map);
			dprintf (D_SECURITY, "ZKM: pre-map: current user is '%s'\n",
					authenticator_->getRemoteUser()?authenticator_->getRemoteUser():"(null)");
			dprintf (D_SECURITY, "ZKM: pre-map: current domain is '%s'\n",
					authenticator_->getRemoteDomain()?authenticator_->getRemoteDomain():"(null)");
			map_authentication_name_to_canonical_name(auth_status, method_used, name_to_map);
		} else {
			dprintf (D_SECURITY, "ZKM: name to map is null, not mapping.\n");
		}
#if defined(HAVE_EXT_GLOBUS)
	} else if (auth_status == CAUTH_GSI ) {
		// Fall back to using the globus mapping mechanism.  GSI is a bit unique in that
		// it may be horribly expensive - or cause a SEGFAULT - to do an authorization callout.
		// Hence, we delay it until after we apply a mapfile or, here, have no map file.
		// nameGssToLocal calls setRemoteFoo directly.
		const char * name_to_map = authenticator_->getAuthenticatedName();
		if (name_to_map) {
			int retval = ((Condor_Auth_X509*)authenticator_)->nameGssToLocal(name_to_map);
			dprintf(D_SECURITY, "nameGssToLocal returned %s\n", retval ? "success" : "failure");
		} else {
			dprintf (D_SECURITY, "ZKM: name to map is null, not calling GSI authorization.\n");
		}
#endif
	}
	// for now, let's be a bit more verbose and print this to D_SECURITY.
	// yeah, probably all of the log lines that start with ZKM: should be
	// updated.  oh, i wish there were a D_ZKM, but alas, we're out of bits.
	if( authenticator_ ) {
		dprintf (D_SECURITY, "ZKM: post-map: current user is '%s'\n",
				 authenticator_->getRemoteUser()?authenticator_->getRemoteUser():"(null)");
		dprintf (D_SECURITY, "ZKM: post-map: current domain is '%s'\n",
				 authenticator_->getRemoteDomain()?authenticator_->getRemoteDomain():"(null)");
		dprintf (D_SECURITY, "ZKM: post-map: current FQU is '%s'\n",
				 authenticator_->getRemoteFQU()?authenticator_->getRemoteFQU():"(null)");
	}

	mySock->allow_one_empty_message();

#if !defined(SKIP_AUTHENTICATION)
	if (retval && retval != 2 && m_key != NULL) {        // will always try to exchange key!
		// This is a hack for now, when we have only one authenticate method
		// this will be gone
		mySock->allow_empty_message_flag = FALSE;
		retval = exchangeKey(*m_key);
		if ( !retval ) {
			errstack->push("AUTHENTICATE",AUTHENTICATE_ERR_KEYEXCHANGE_FAILED,
			"Failed to securely exchange session key");
		}
		dprintf(D_SECURITY, "AUTHENTICATE: Result of end of authenticate is %d.\n", retval);
		mySock->allow_one_empty_message();
	}
#endif

	return ( retval );
}
예제 #17
0
ClassAd*
readJobAd( void )
{
    ClassAd* ad = NULL;
    bool is_stdin = false;
    bool read_something = false;

    ASSERT( job_ad_file );

    if( job_ad_file[0] == '-' && job_ad_file[1] == '\0' ) {
        fp = stdin;
        is_stdin = true;
    } else {
        if (fp == NULL) {
            fp = safe_fopen_wrapper_follow( job_ad_file, "r" );
            if( ! fp ) {
                EXCEPT( "Failed to open ClassAd file (%s): %s (errno %d)",
                        job_ad_file, strerror(errno), errno );
            }
        }
    }

    dprintf( D_FULLDEBUG, "Reading job ClassAd from %s\n",
             is_stdin ? "STDIN" : job_ad_file );

    ad = new ClassAd;
    MyString line;
    while( line.readLine(fp) ) {
        read_something = true;
        line.chomp();
        if( line[0] == '#' ) {
            dprintf( D_JOB, "IGNORING COMMENT: %s\n", line.Value() );
            continue;
        }
        if( line == "***" ) {
            dprintf( D_JOB, "Saw ClassAd delimitor, stopping\n" );
            break;
        }
        if( ! ad->Insert(line.Value()) ) {
            EXCEPT( "Failed to insert \"%s\" into ClassAd!", line.Value() );
        }
    }
    if( ! read_something ) {
        EXCEPT( "reading ClassAd from (%s): file is empty",
                is_stdin ? "STDIN" : job_ad_file );
    }
    if( IsDebugVerbose(D_JOB) ) {
        ad->dPrint( D_JOB );
    }

    // For debugging, see if there's a special attribute in the
    // job ad that sends us into an infinite loop, waiting for
    // someone to attach with a debugger
    int shadow_should_wait = 0;
    ad->LookupInteger( ATTR_SHADOW_WAIT_FOR_DEBUG,
                       shadow_should_wait );
    if( shadow_should_wait ) {
        dprintf( D_ALWAYS, "Job requested shadow should wait for "
                 "debugger with %s=%d, going into infinite loop\n",
                 ATTR_SHADOW_WAIT_FOR_DEBUG, shadow_should_wait );
        while( shadow_should_wait ) { }
    }

    return ad;
}
예제 #18
0
// Timeout() is called when a select() time out.  Returns number of seconds
// until next timeout event, a 0 if there are no more events, or a -1 if
// called while a handler is active (i.e. handler calls Timeout;
// Timeout is not re-entrant).
int
TimerManager::Timeout(int * pNumFired /*= NULL*/, double * pruntime /*=NULL*/)
{
	int				result, timer_check_cntr;
	time_t			now, time_sample;
	int				num_fires = 0;	// num of handlers called in this timeout

    if (pNumFired) *pNumFired = 0;

	if ( in_timeout != NULL ) {
		dprintf(D_DAEMONCORE,"DaemonCore Timeout() called and in_timeout is non-NULL\n");
		if ( timer_list == NULL ) {
			result = 0;
		} else {
			result = (timer_list->when) - time(NULL);
		}
		if ( result < 0 ) {
			result = 0;
		}
		return(result);
	}
		
	dprintf( D_DAEMONCORE, "In DaemonCore Timeout()\n");

	if (timer_list == NULL) {
		dprintf( D_DAEMONCORE, "Empty timer list, nothing to do\n" );
	}

	time(&now);
	timer_check_cntr = 0;

	DumpTimerList(D_DAEMONCORE | D_FULLDEBUG);

	// loop until all handlers that should have been called by now or before
	// are invoked and renewed if periodic.  Remember that NewTimer and CancelTimer
	// keep the timer_list happily sorted on "when" for us.  We use "now" as a 
	// variable so that if some of these handler functions run for a long time,
	// we do not sit in this loop forever.
	// we make certain we do not call more than "max_fires" handlers in a 
	// single timeout --- this ensures that timers don't starve out the rest
	// of daemonCore if a timer handler resets itself to 0.
	while( (timer_list != NULL) && (timer_list->when <= now ) && 
		   (num_fires++ < MAX_FIRES_PER_TIMEOUT)) 
	{
		// DumpTimerList(D_DAEMONCORE | D_FULLDEBUG);

		in_timeout = timer_list;

		// In some cases, resuming from a suspend can cause the system
		// clock to become temporarily skewed, causing crazy things to 
		// happen with our timers (particularly for sending updates to
		// the collector). So, to correct for such skews, we routinely
		// check to make sure that 'now' is not in the future.

		timer_check_cntr++; 

			// since time() is somewhat expensive, we 
			// only check every 10 times we loop 
			
		if ( timer_check_cntr > 10 ) {

			timer_check_cntr = 0;

			time(&time_sample);
			if (now > time_sample) {
				dprintf(D_ALWAYS, "DaemonCore: Clock skew detected "
					"(time=%ld; now=%ld). Resetting TimerManager's "
					"notion of 'now'\n", (long) time_sample, 
					(long) now);
				now = time_sample;
			}
		}

		// Update curr_dataptr for GetDataPtr()
		curr_dataptr = &(in_timeout->data_ptr);

		// Initialize our flag so we know if ResetTimer was called.
		did_reset = false;
		did_cancel = false;

		// Log a message before calling handler, but only if
		// D_FULLDEBUG is also enabled.
		if (IsDebugVerbose(D_COMMAND)) {
			dprintf(D_COMMAND, "Calling Timer handler %d (%s)\n",
					in_timeout->id, in_timeout->event_descrip);
		}

		if( in_timeout->timeslice ) {
			in_timeout->timeslice->setStartTimeNow();
		}

		// Now we call the registered handler.  If we were told that the handler
		// is a c++ method, we call the handler from the c++ object referenced 
		// by service*.  If we were told the handler is a c function, we call
		// it and pass the service* as a parameter.
		if ( in_timeout->handlercpp ) {
			// typedef int (*TimerHandlercpp)()
			((in_timeout->service)->*(in_timeout->handlercpp))();
		} else {
			// typedef int (*TimerHandler)()
			(*(in_timeout->handler))();
		}

		if( in_timeout->timeslice ) {
			in_timeout->timeslice->setFinishTimeNow();
		}

		if (IsDebugVerbose(D_COMMAND)) {
			if( in_timeout->timeslice ) {
				dprintf(D_COMMAND, "Return from Timer handler %d (%s) - took %.3fs\n",
						in_timeout->id, in_timeout->event_descrip,
						in_timeout->timeslice->getLastDuration() );
			}
			else {
				dprintf(D_COMMAND, "Return from Timer handler %d (%s)\n",
						in_timeout->id, in_timeout->event_descrip);
			}
		}

		if (pruntime) {           
			*pruntime = daemonCore->dc_stats.AddRuntime(in_timeout->event_descrip, *pruntime);
		}

        // Make sure we didn't leak our priv state
		daemonCore->CheckPrivState();

		// Clear curr_dataptr
		curr_dataptr = NULL;

		if ( did_cancel ) {
			// Timer was canceled inside its handler. All we need to do
			// is delete it.
			DeleteTimer( in_timeout );
		} else if ( !did_reset ) {
			// here we remove the timer we just serviced, or renew it if it is 
			// periodic.

			// If a new timer was added at a time in the past
			// (possible when resetting a timeslice timer), then
			// it may have landed before the timer we just processed,
			// meaning that we cannot assume prev==NULL in the call
			// to RemoveTimer() below.

			Timer *prev = NULL;
			ASSERT( GetTimer(in_timeout->id,&prev) == in_timeout );
			RemoveTimer( in_timeout, prev );

			if ( in_timeout->period > 0 || in_timeout->timeslice ) {
				in_timeout->period_started = time(NULL);
				in_timeout->when = in_timeout->period_started;
				if ( in_timeout->timeslice ) {
					in_timeout->when += in_timeout->timeslice->getTimeToNextRun();
				} else {
					if( in_timeout->period == TIMER_NEVER ) {
						in_timeout->when = TIME_T_NEVER;
					} else {
						in_timeout->when += in_timeout->period;
					}
				}
				InsertTimer( in_timeout );
			} else {
				// timer is not perodic; it is just a one-time event.  we just called
				// the handler, so now just delete it. 
				DeleteTimer( in_timeout );
			}
		}
	}  // end of while loop


	// set result to number of seconds until next event.  get an update on the
	// time from time() in case the handlers we called above took significant time.
	if ( timer_list == NULL ) {
		// we set result to be -1 so that we do not busy poll.
		// a -1 return value will tell the DaemonCore:Driver to use select with
		// no timeout.
		result = -1;
	} else {
		result = (timer_list->when) - time(NULL);
		if (result < 0)
			result = 0;
	}

	dprintf( D_DAEMONCORE, "DaemonCore Timeout() Complete, returning %d \n",result);
    if (pNumFired) *pNumFired = num_fires;
	in_timeout = NULL;
	return(result);
}
예제 #19
0
int Authentication::authenticate_inner( char *hostAddr, const char* auth_methods,
		CondorError* errstack, int timeout)
{
#if defined(SKIP_AUTHENTICATION)
	dprintf(D_ALWAYS, "Skipping....\n");
	/*
	errstack->push ( "AUTHENTICATE", AUTHENTICATE_ERR_NOT_BUILT,
			"this condor was built with SKIP_AUTHENTICATION");
	*/
	return 0;
#else
	Condor_Auth_Base * auth = NULL;
	int auth_timeout_time = time(0) + timeout;

	if (IsDebugVerbose(D_SECURITY)) {
		if (hostAddr) {
			dprintf ( D_SECURITY, "AUTHENTICATE: in authenticate( addr == '%s', "
					"methods == '%s')\n", hostAddr, auth_methods);
		} else {
			dprintf ( D_SECURITY, "AUTHENTICATE: in authenticate( addr == NULL, "
					"methods == '%s')\n", auth_methods);
		}
	}

	MyString methods_to_try = auth_methods;

	auth_status = CAUTH_NONE;
	method_used = NULL;
 
	while (auth_status == CAUTH_NONE ) {
		if (timeout>0 && auth_timeout_time <= time(0)) {
			dprintf(D_SECURITY, "AUTHENTICATE: exceeded %ds timeout\n",
					timeout);
			errstack->pushf( "AUTHENTICATE", AUTHENTICATE_ERR_TIMEOUT, "exceeded %ds timeout during authentication", timeout );
			break;
		}
		if (IsDebugVerbose(D_SECURITY)) {
			dprintf(D_SECURITY, "AUTHENTICATE: can still try these methods: %s\n", methods_to_try.Value());
		}

		int firm = handshake(methods_to_try);

		if ( firm < 0 ) {
			dprintf(D_ALWAYS, "AUTHENTICATE: handshake failed!\n");
			errstack->push( "AUTHENTICATE", AUTHENTICATE_ERR_HANDSHAKE_FAILED, "Failure performing handshake" );
			break;
		}

		char* method_name = NULL;
		switch ( firm ) {
#if defined(HAVE_EXT_GLOBUS)
			case CAUTH_GSI:
				auth = new Condor_Auth_X509(mySock);
				method_name = strdup("GSI");
				break;
#endif /* HAVE_EXT_GLOBUS */

#ifdef HAVE_EXT_OPENSSL
            case CAUTH_SSL:
                auth = new Condor_Auth_SSL(mySock);
                method_name = strdup("SSL");
                break;
#endif

#if defined(HAVE_EXT_KRB5) 
			case CAUTH_KERBEROS:
				auth = new Condor_Auth_Kerberos(mySock);
				method_name = strdup("KERBEROS");
				break;
#endif

#ifdef HAVE_EXT_OPENSSL  // 3DES is the prequisite for passwd auth
			case CAUTH_PASSWORD:
				auth = new Condor_Auth_Passwd(mySock);
				method_name = strdup("PASSWORD");
				break;
#endif
 
#if defined(WIN32)
			case CAUTH_NTSSPI:
				auth = new Condor_Auth_SSPI(mySock);
				method_name = strdup("NTSSPI");
				break;
#else
			case CAUTH_FILESYSTEM:
				auth = new Condor_Auth_FS(mySock);
				method_name = strdup("FS");
				break;
			case CAUTH_FILESYSTEM_REMOTE:
				auth = new Condor_Auth_FS(mySock, 1);
				method_name = strdup("FS_REMOTE");
				break;
#endif /* !defined(WIN32) */
			case CAUTH_CLAIMTOBE:
				auth = new Condor_Auth_Claim(mySock);
				method_name = strdup("CLAIMTOBE");
				break;
 
			case CAUTH_ANONYMOUS:
				auth = new Condor_Auth_Anonymous(mySock);
				method_name = strdup("ANONYMOUS");
				break;
 
			case CAUTH_NONE:
				dprintf(D_SECURITY|D_FULLDEBUG,"AUTHENTICATE: no available authentication methods succeeded!\n");
				errstack->push("AUTHENTICATE", AUTHENTICATE_ERR_OUT_OF_METHODS,
						"Failed to authenticate with any method");
				return 0;

			default:
				dprintf(D_ALWAYS,"AUTHENTICATE: unsupported method: %i, failing.\n", firm);
				errstack->pushf("AUTHENTICATE", AUTHENTICATE_ERR_OUT_OF_METHODS,
						"Failure.  Unsupported method: %i", firm);
				return 0;
		}


		if (IsDebugVerbose(D_SECURITY)) {
			dprintf(D_SECURITY, "AUTHENTICATE: will try to use %d (%s)\n", firm,
					(method_name?method_name:"?!?") );
		}

		//------------------------------------------
		// Now authenticate
		//------------------------------------------
		bool auth_rc = auth->authenticate(hostAddr, errstack);

			// check to see if the auth IP is the same as the socket IP
		if( auth_rc ) {
			char const *sockip = mySock->peer_ip_str();
			char const *authip = auth->getRemoteHost() ;

			auth_rc = !sockip || !authip || !strcmp(sockip,authip);

			if (!auth_rc && !param_boolean( "DISABLE_AUTHENTICATION_IP_CHECK", false)) {
				errstack->pushf("AUTHENTICATE", AUTHENTICATE_ERR_METHOD_FAILED,
								"authenticated remote host does not match connection address (%s vs %s)", authip, sockip );
				dprintf (D_ALWAYS, "AUTHENTICATE: ERROR: authenticated remot ehost does not match connection address (%s vs %s); configure DISABLE_AUTHENTICATION_IP_CHECK=TRUE if this check should be skipped\n",authip,sockip);
			}
		}

		if( !auth_rc ) {
			delete auth;
			auth = NULL;

			errstack->pushf("AUTHENTICATE", AUTHENTICATE_ERR_METHOD_FAILED,
					"Failed to authenticate using %s", method_name );

			//if authentication failed, try again after removing from client tries
			if ( mySock->isClient() ) {
				// need to remove this item from the MyString!!  perhaps there is a
				// better way to do this...  anyways, 'firm' is equal to the bit value
				// of a particular method, so we'll just convert each item in the list
				// and keep it if it's not that particular bit.
				StringList meth_iter( methods_to_try.Value() );
				meth_iter.rewind();
				MyString new_list;
				char *tmp = NULL;
				while( (tmp = meth_iter.next()) ) {
					int that_bit = SecMan::getAuthBitmask( tmp );

					// keep if this isn't the failed method.
					if (firm != that_bit) {
						// and of course, keep the comma's correct.
						if (new_list.Length() > 0) {
							new_list += ",";
						}
						new_list += tmp;
					}
				}

				// trust the copy constructor. :)
				methods_to_try = new_list;
			}

			dprintf(D_SECURITY,"AUTHENTICATE: method %d (%s) failed.\n", firm,
					(method_name?method_name:"?!?"));
		} else {
			// authentication succeeded.  store the object (we may call upon
			// its wrapper functions) and set the auth_status of this sock to
			// the bitmask method we used and the method_used to the string
			// name.  (string name is obtained above because there is currently
			// no bitmask -> string map)
			authenticator_ = auth;
			auth_status = authenticator_->getMode();
			if (method_name) {
				method_used = strdup(method_name);
			} else {
				method_used = NULL;
			}
		}
		free (method_name);
	}

	//if none of the methods succeeded, we fall thru to default "none" from above
	int retval = ( auth_status != CAUTH_NONE );
	if (IsDebugVerbose(D_SECURITY)) {
		dprintf(D_SECURITY, "AUTHENTICATE: auth_status == %i (%s)\n", auth_status,
				(method_used?method_used:"?!?") );
	}
	dprintf(D_SECURITY, "Authentication was a %s.\n", retval == 1 ? "Success" : "FAILURE" );


	// at this point, all methods have set the raw authenticated name available
	// via getAuthenticatedName().

	if(authenticator_) {
		dprintf (D_SECURITY, "ZKM: setting default map to %s\n",
				 authenticator_->getRemoteFQU()?authenticator_->getRemoteFQU():"(null)");
	}

	// check to see if CERTIFICATE_MAPFILE was defined.  if so, use it.  if
	// not, do nothing.  the user and domain have been filled in by the
	// authentication method itself, so just leave that alone.
	char * cert_map_file = param("CERTIFICATE_MAPFILE");
	bool use_mapfile = (cert_map_file != NULL);
	if (cert_map_file) {
		free(cert_map_file);
		cert_map_file = 0;
	}

	// if successful so far, invoke the security MapFile.  the output of that
	// is the "canonical user".  if that has an '@' sign, split it up on the
	// last '@' and set the user and domain.  if there is more than one '@',
	// the user will contain the leftovers after the split and the domain
	// always has none.
	if (retval && use_mapfile) {
		const char * name_to_map = authenticator_->getAuthenticatedName();
		if (name_to_map) {
			dprintf (D_SECURITY, "ZKM: name to map is '%s'\n", name_to_map);
			dprintf (D_SECURITY, "ZKM: pre-map: current user is '%s'\n",
					authenticator_->getRemoteUser()?authenticator_->getRemoteUser():"(null)");
			dprintf (D_SECURITY, "ZKM: pre-map: current domain is '%s'\n",
					authenticator_->getRemoteDomain()?authenticator_->getRemoteDomain():"(null)");
			map_authentication_name_to_canonical_name(auth_status, method_used, name_to_map);
		} else {
			dprintf (D_SECURITY, "ZKM: name to map is null, not mapping.\n");
		}
	}
	// for now, let's be a bit more verbose and print this to D_SECURITY.
	// yeah, probably all of the log lines that start with ZKM: should be
	// updated.  oh, i wish there were a D_ZKM, but alas, we're out of bits.
	if( authenticator_ ) {
		dprintf (D_SECURITY, "ZKM: post-map: current user is '%s'\n",
				 authenticator_->getRemoteUser()?authenticator_->getRemoteUser():"(null)");
		dprintf (D_SECURITY, "ZKM: post-map: current domain is '%s'\n",
				 authenticator_->getRemoteDomain()?authenticator_->getRemoteDomain():"(null)");
		dprintf (D_SECURITY, "ZKM: post-map: current FQU is '%s'\n",
				 authenticator_->getRemoteFQU()?authenticator_->getRemoteFQU():"(null)");
	}

	mySock->allow_one_empty_message();
	return ( retval );
#endif /* SKIP_AUTHENTICATION */
}