Control: tags -1 patch

Please find attached the patch to address CVE-2019-18823 for version
8.6.8~dfsg.1-2, also applied in Debian 10 "Buster".

Markus
From: Markus Koschany <a...@debian.org>
Date: Fri, 20 May 2022 14:08:49 +0200
Subject: CVE-2019-18823

Bug-Debian: https://bugs.debian.org/963777
Origin: https://github.com/htcondor/htcondor/commit/95eaee86e7ad3852c17df46a1b8b193dabd1fd14
Origin: https://github.com/htcondor/htcondor/commit/07e33c8b14aa00e04d045d4d79c963db082a3129
Origin: https://github.com/htcondor/htcondor/commit/cbcb93695a932d511c1c7bd40aed1eabeff01d8d
Origin: https://github.com/htcondor/htcondor/commit/3916209123a8ef762b7a9cd84ca0cf8b2cd99716
Origin: https://github.com/htcondor/htcondor/commit/5c84c6f0b3db4eda1eec42c2c708069bb9393f0b
---
 src/condor_daemon_client/dc_schedd.cpp   |  2 +-
 src/condor_daemon_client/dc_startd.cpp   | 40 +++++++++++++++++++++++++++---
 src/condor_includes/condor_commands.h    |  2 ++
 src/condor_schedd.V6/qmgmt.cpp           | 26 +++++++++++++++++---
 src/condor_schedd.V6/qmgmt.h             |  3 +++
 src/condor_schedd.V6/qmgmt_receivers.cpp | 14 +++--------
 src/condor_schedd.V6/schedd.cpp          |  6 ++---
 src/condor_shadow.V6.1/shadow.cpp        |  4 ++-
 src/condor_startd.V6/Resource.cpp        |  4 +--
 src/condor_startd.V6/command.cpp         | 28 ++++++++++++++-------
 src/condor_startd.V6/command.h           |  2 +-
 src/condor_starter.V6.1/baseStarter.cpp  |  4 +--
 src/condor_status.V6/prettyPrint.cpp     |  2 +-
 src/condor_tools/history.cpp             |  4 +--
 src/condor_tools/transform_ads.cpp       |  4 +--
 src/condor_utils/compat_classad.cpp      | 42 +++++++++++++++++++++++++++-----
 src/condor_utils/compat_classad.h        |  8 +++---
 src/condor_utils/file_transfer.cpp       |  8 +++++-
 src/condor_who/who.cpp                   |  4 +--
 19 files changed, 153 insertions(+), 54 deletions(-)

diff --git a/src/condor_daemon_client/dc_schedd.cpp b/src/condor_daemon_client/dc_schedd.cpp
index fe935b0..bf291fa 100644
--- a/src/condor_daemon_client/dc_schedd.cpp
+++ b/src/condor_daemon_client/dc_schedd.cpp
@@ -1878,7 +1878,7 @@ bool DCSchedd::getJobConnectInfo(
 
 	if( IsFulldebug(D_FULLDEBUG) ) {
 		std::string adstr;
-		sPrintAd(adstr, output, true);
+		sPrintAd(adstr, output);
 		dprintf(D_FULLDEBUG,"Response for GET_JOB_CONNECT_INFO:\n%s\n",
 				adstr.c_str());
 	}
diff --git a/src/condor_daemon_client/dc_startd.cpp b/src/condor_daemon_client/dc_startd.cpp
index be0101f..9e5693c 100644
--- a/src/condor_daemon_client/dc_startd.cpp
+++ b/src/condor_daemon_client/dc_startd.cpp
@@ -135,6 +135,12 @@ ClaimStartdMsg::writeMsg( DCMessenger * /*messenger*/, Sock *sock ) {
 	m_job_ad.Assign("_condor_SEND_PAIRED_SLOT",
 		param_boolean("CLAIM_PAIRED_SLOT",true));
 
+		// Insert an attribute in the request ad to inform the
+		// startd that this schedd is capable of understanding
+		// the newer protocol where any claim id in the response
+		// is encrypted.
+	m_job_ad.Assign("_condor_SECURE_CLAIM_ID", true);
+
 	if( !sock->put_secret( m_claim_id.c_str() ) ||
 	    !putClassAd( sock, m_job_ad ) ||
 	    !sock->put( scheduler_addr_to_send.c_str() ) ||
@@ -234,14 +240,29 @@ ClaimStartdMsg::readMsg( DCMessenger * /*messenger*/, Sock *sock ) {
 		Reply of 4 (REQUEST_CLAIM_PAIR) means claim accepted by a slot
 		  that is paired, and the partner slot ad and claim id will be
 		  sent next.
+		Reply of 5 (REQUEST_CLAIM_LEFTOVERS_2) is the same as 3, but
+		  the claim id is encrypted.
+		Reply of 6 (REQUEST_CLAIM_PAIR_2) is the same as 4, but
+		  the claim id is encrypted.
 	*/
 
 	if( m_reply == OK ) {
 			// no need to log success, because DCMsg::reportSuccess() will
 	} else if( m_reply == NOT_OK ) {
 		dprintf( failureDebugLevel(), "Request was NOT accepted for claim %s\n", description() );
-	} else if( m_reply == REQUEST_CLAIM_LEFTOVERS ) {
-	 	if( !sock->get(m_leftover_claim_id) ||
+	} else if( m_reply == REQUEST_CLAIM_LEFTOVERS || m_reply == REQUEST_CLAIM_LEFTOVERS_2 ) {
+		bool recv_ok = false;
+		if ( m_reply == REQUEST_CLAIM_LEFTOVERS_2 ) {
+			char *val = NULL;
+			recv_ok = sock->get_secret(val);
+			if ( recv_ok ) {
+				m_leftover_claim_id = val;
+				free(val);
+			}
+		} else {
+			recv_ok = sock->get(m_leftover_claim_id);
+		}
+		if( !recv_ok ||
 			!getClassAd( sock, m_leftover_startd_ad )  ) 
 		{
 			// failed to read leftover partitionable slot info
@@ -256,8 +277,19 @@ ClaimStartdMsg::readMsg( DCMessenger * /*messenger*/, Sock *sock ) {
 			// change reply to OK cuz claim was a success
 			m_reply = OK;
 		}
-	} else if( m_reply == REQUEST_CLAIM_PAIR ) {
-		if( !sock->get(m_paired_claim_id) ||
+	} else if( m_reply == REQUEST_CLAIM_PAIR || m_reply == REQUEST_CLAIM_PAIR_2 ) {
+		bool recv_ok = false;
+		if ( m_reply == REQUEST_CLAIM_PAIR_2 ) {
+			char *val = NULL;
+			recv_ok = sock->get_secret(val);
+			if ( recv_ok ) {
+				m_paired_claim_id = val;
+				free(val);
+			}
+		} else {
+			recv_ok = sock->get(m_paired_claim_id);
+		}
+		if( !recv_ok ||
 			!getClassAd( sock, m_paired_startd_ad ) )
 		{
 			// failed to read paired slot info
diff --git a/src/condor_includes/condor_commands.h b/src/condor_includes/condor_commands.h
index c6b029c..5656c27 100644
--- a/src/condor_includes/condor_commands.h
+++ b/src/condor_includes/condor_commands.h
@@ -536,6 +536,8 @@ NAMETABLE_DIRECTIVE:END_SECTION:collector
 /* Replies specific to the REQUEST_CLAIM command */
 #define REQUEST_CLAIM_LEFTOVERS		3
 #define REQUEST_CLAIM_PAIR			4
+#define REQUEST_CLAIM_LEFTOVERS_2	5
+#define REQUEST_CLAIM_PAIR_2		6
 
 /* Replies specific to the SWAP_CLAIM_AND_ACTIVATION command */
 #define SWAP_CLAIM_ALREADY_SWAPPED	4
diff --git a/src/condor_schedd.V6/qmgmt.cpp b/src/condor_schedd.V6/qmgmt.cpp
index f052531..e6dd116 100644
--- a/src/condor_schedd.V6/qmgmt.cpp
+++ b/src/condor_schedd.V6/qmgmt.cpp
@@ -158,7 +158,7 @@ static QmgmtPeer *Q_SOCK = NULL;
 // running.  Used by SuperUserAllowedToSetOwnerTo().
 static HashTable<MyString,int> owner_history(MyStringHash);
 
-int		do_Q_request(ReliSock *,bool &may_fork);
+int		do_Q_request(QmgmtPeer &,bool &may_fork);
 void	FindPrioJob(PROC_ID &);
 
 static bool qmgmt_was_initialized = false;
@@ -505,6 +505,7 @@ QmgmtPeer::QmgmtPeer()
 	myendpoint = NULL;
 	sock = NULL;
 	transaction = NULL;
+	readonly = false;
 	allow_protected_attr_changes_by_superuser = true;
 
 	unset();
@@ -574,6 +575,16 @@ QmgmtPeer::setEffectiveOwner(char const *o)
 	return true;
 }
 
+bool
+QmgmtPeer::setReadOnly(bool val)
+{
+	bool old_val = readonly;
+
+	readonly = val;
+
+	return old_val;
+}
+
 void
 QmgmtPeer::unset()
 {
@@ -598,6 +609,7 @@ QmgmtPeer::unset()
 	next_proc_num = 0;
 	active_cluster_num = -1;	
 	xact_start_time = 0;	// time at which the current transaction was started
+	readonly = false;
 }
 
 const char*
@@ -1626,6 +1638,12 @@ OwnerCheck(int cluster_id,int proc_id)
 bool
 OwnerCheck(ClassAd *ad, const char *test_owner)
 {
+	if ( Q_SOCK->getReadOnly() ) {
+		errno = EACCES;
+		dprintf( D_FULLDEBUG, "OwnerCheck: reject read-only client\n" );
+		return false;
+	}
+
 	// check if the IP address of the peer has daemon core write permission
 	// to the schedd.  we have to explicitly check here because all queue
 	// management commands come in via one sole daemon core command which
@@ -1849,7 +1867,7 @@ unsetQSock()
 
 
 int
-handle_q(Service *, int, Stream *sock)
+handle_q(Service *, int cmd, Stream *sock)
 {
 	int	rval;
 	bool all_good;
@@ -1868,13 +1886,15 @@ handle_q(Service *, int, Stream *sock)
 	}
 	ASSERT(Q_SOCK);
 
+	Q_SOCK->setReadOnly(cmd == QMGMT_READ_CMD);
+
 	BeginTransaction();
 
 	bool may_fork = false;
 	ForkStatus fork_status = FORK_FAILED;
 	do {
 		/* Probably should wrap a timer around this */
-		rval = do_Q_request( Q_SOCK->getReliSock(), may_fork );
+		rval = do_Q_request( *Q_SOCK, may_fork );
 
 		if( may_fork && fork_status == FORK_FAILED ) {
 			fork_status = schedd_forker.NewJob();
diff --git a/src/condor_schedd.V6/qmgmt.h b/src/condor_schedd.V6/qmgmt.h
index 42e86b2..e090adb 100644
--- a/src/condor_schedd.V6/qmgmt.h
+++ b/src/condor_schedd.V6/qmgmt.h
@@ -55,6 +55,8 @@ class QmgmtPeer {
 		bool setAllowProtectedAttrChanges(bool val);
 		bool getAllowProtectedAttrChanges() { return allow_protected_attr_changes_by_superuser; }
 
+		bool setReadOnly(bool val);
+		bool getReadOnly() const { return readonly; }
 		ReliSock *getReliSock() const { return sock; };
 		const CondorVersionInfo *get_peer_version() const { return sock->get_peer_version(); };
 
@@ -68,6 +70,7 @@ class QmgmtPeer {
 	protected:
 
 		char *owner;  
+		bool readonly;
 		bool allow_protected_attr_changes_by_superuser;
 		char *fquser;  // owner@domain
 		char *myendpoint; 
diff --git a/src/condor_schedd.V6/qmgmt_receivers.cpp b/src/condor_schedd.V6/qmgmt_receivers.cpp
index b71b2b6..7d9b46c 100644
--- a/src/condor_schedd.V6/qmgmt_receivers.cpp
+++ b/src/condor_schedd.V6/qmgmt_receivers.cpp
@@ -50,11 +50,12 @@ static bool QmgmtMayAccessAttribute( char const *attr_name ) {
 }
 
 int
-do_Q_request(ReliSock *syscall_sock,bool &may_fork)
+do_Q_request(QmgmtPeer &Q_PEER, bool &may_fork)
 {
 	int	request_num = -1;
 	int	rval;
 
+	ReliSock *syscall_sock = Q_PEER.getReliSock();
 	syscall_sock->decode();
 
 	assert( syscall_sock->code(request_num) );
@@ -97,12 +98,6 @@ do_Q_request(ReliSock *syscall_sock,bool &may_fork)
 	{
 		// dprintf( D_ALWAYS, "InitializeReadOnlyConnection()\n" );
 
-		// Since InitializeConnection() does nothing, and we need
-		// to record the fact that this is a read-only connection,
-		// but we have to do it in the socket (since we don't have
-		// any other persistent data structure, and it's probably
-		// the right place anyway), set the FQU.
-		//
 		// We need to record if this is a read-only connection so that
 		// we can avoid expanding $$ in GetJobAd; simply checking if the
 		// connection is authenticated isn't sufficient, because the
@@ -110,7 +105,7 @@ do_Q_request(ReliSock *syscall_sock,bool &may_fork)
 		// be authenticated by a previous authenticated connection from
 		// the same address (when using host-based security) less than
 		// the expiration period ago.
-		syscall_sock->setFullyQualifiedUser( "read-only" );
+		Q_PEER.setReadOnly(true);
 
 		// same as InitializeConnection but no authenticate()
 		InitializeConnection( NULL, NULL );
@@ -819,8 +814,7 @@ do_Q_request(ReliSock *syscall_sock,bool &may_fork)
 		// Only fetch the jobad for legal values of cluster/proc
 		if( cluster_id >= 1 ) {
 			if( proc_id >= 0 ) {
-				const char * fqu = syscall_sock->getFullyQualifiedUser();
-				if( fqu != NULL && strcmp( fqu, "read-only" ) != 0 ) {
+				if( !Q_PEER.getReadOnly() ) {
 					// expand $$() macros in the jobad as required by GridManager.
 					// The GridManager depends on the fact that the following call
 					// expands $$ and saves the expansions to disk in case of
diff --git a/src/condor_schedd.V6/schedd.cpp b/src/condor_schedd.V6/schedd.cpp
index b751ced..5a38e9e 100644
--- a/src/condor_schedd.V6/schedd.cpp
+++ b/src/condor_schedd.V6/schedd.cpp
@@ -2597,7 +2597,7 @@ int Scheduler::guessJobSlotWeight(JobQueueJob * job)
 			ad->Assign(ATTR_MEMORY, 1024);
 			ad->Assign(ATTR_DISK, 1024);
 			dprintf(D_ALWAYS, "Creating slotWeightGuessAd as:\n");
-			dPrintAd(D_ALWAYS, *ad, false);
+			dPrintAd(D_ALWAYS, *ad);
 		}
 	}
 
@@ -9071,7 +9071,7 @@ Scheduler::spawnJobHandlerRaw( shadow_rec* srec, const char* path,
 			// handler is now alive and can read from the pipe.
 		ASSERT( job_ad );
 		MyString ad_str;
-		sPrintAd(ad_str, *job_ad);
+		sPrintAdWithSecrets(ad_str, *job_ad);
 		const char* ptr = ad_str.Value();
 		int len = ad_str.Length();
 		while (len) {
@@ -9705,7 +9705,7 @@ Scheduler::start_sched_universe_job(PROC_ID* job_id)
 				dprintf ( D_FAILURE|D_ALWAYS, "Open of %s failed (%s, errno=%d).\n", job_ad_path.c_str(), strerror(errno), errno );
 			} else {
 				// fPrindAd does not have any usable error reporting.
-				fPrintAd(job_ad_fp, *userJob, true);
+				fPrintAd(job_ad_fp, *userJob);
 				wrote_job_ad = true;
 				fclose(job_ad_fp);
 			}
diff --git a/src/condor_shadow.V6.1/shadow.cpp b/src/condor_shadow.V6.1/shadow.cpp
index e9e4f6d..ff7b09e 100644
--- a/src/condor_shadow.V6.1/shadow.cpp
+++ b/src/condor_shadow.V6.1/shadow.cpp
@@ -122,7 +122,7 @@ UniShadow::init( ClassAd* job_ad, const char* schedd_addr, const char *xfer_queu
 	
 		// In this case we just pass the pointer along...
 	remRes->setJobAd( jobAd );
-	
+
 		// Register command which gets updates from the starter
 		// on the job's image size, cpu usage, etc.  Each kind of
 		// shadow implements it's own version of this to deal w/ it
@@ -132,6 +132,7 @@ UniShadow::init( ClassAd* job_ad, const char* schedd_addr, const char *xfer_queu
 						  (CommandHandlercpp)&UniShadow::updateFromStarter, 
 						  "UniShadow::updateFromStarter", this, DAEMON );
 
+#if ! defined( WIN32 )
 		// Register command which the starter uses to fetch a user
 		// credential if it needs to.
 	daemonCore->
@@ -139,6 +140,7 @@ UniShadow::init( ClassAd* job_ad, const char* schedd_addr, const char *xfer_queu
 						  (CommandHandler)&get_cred_handler,
 						  "get_cred_handler", NULL, DAEMON, D_COMMAND,
 						  true /*force authentication*/ );
+#endif
 }
 
 void
diff --git a/src/condor_startd.V6/Resource.cpp b/src/condor_startd.V6/Resource.cpp
index c78c1ba..27b545b 100644
--- a/src/condor_startd.V6/Resource.cpp
+++ b/src/condor_startd.V6/Resource.cpp
@@ -3300,9 +3300,9 @@ Resource * initialize_resource(Resource * rip, ClassAd * req_classad, Claim* &le
 					dprintf(D_MATCH | D_FULLDEBUG,
 						"STARTD Requirements do not match, %s MODIFY_REQUEST_EXPR_ edits. Job ad was ============================\n", 
 						unmodified_req_classad ? "with" : "w/o");
-					dPrintAd(D_MATCH | D_FULLDEBUG, *req_classad, true);
+					dPrintAd(D_MATCH | D_FULLDEBUG, *req_classad);
 					dprintf(D_MATCH | D_FULLDEBUG, "Machine ad was ============================\n");
-					dPrintAd(D_MATCH | D_FULLDEBUG, *mach_classad, true);
+					dPrintAd(D_MATCH | D_FULLDEBUG, *mach_classad);
 				}
 				if (unmodified_req_classad) {
 					// our modified req_classad no longer matches, put back the original
diff --git a/src/condor_startd.V6/command.cpp b/src/condor_startd.V6/command.cpp
index ef5fbea..053cbbc 100644
--- a/src/condor_startd.V6/command.cpp
+++ b/src/condor_startd.V6/command.cpp
@@ -1217,6 +1217,7 @@ request_claim( Resource* rip, Claim *claim, char* id, Stream* stream )
 	char *client_addr = NULL;
 	int interval;
 	ClaimIdParser idp(id);
+	bool secure_claim_id = false;
 
 		// Used in ABORT macro, yuck
 	bool new_dynamic_slot = false;
@@ -1321,6 +1322,10 @@ request_claim( Resource* rip, Claim *claim, char* id, Stream* stream )
 		ABORT;
 	}
 
+		// If we include a claim id in our response, should it be
+		// encrypted? In the old protocol, it was sent in the clear.
+	req_classad->LookupBool("_condor_SECURE_CLAIM_ID", secure_claim_id);
+
 		// At this point, the schedd has registered this socket (stream)
 		// and likely has gone off to service other requests.  Thus, 
 		// we need change the timeout on the socket to the schedd to be
@@ -1530,7 +1535,7 @@ request_claim( Resource* rip, Claim *claim, char* id, Stream* stream )
 		// function after the preemption has completed when the startd
 		// is finally ready to reply to the and finish the claiming
 		// process.
-	accept_request_claim( rip, leftover_claim, and_pair );
+	accept_request_claim( rip, secure_claim_id, leftover_claim, and_pair );
 
 		// We always need to return KEEP_STREAM so that daemon core
 		// doesn't try to delete the stream we've already deleted.
@@ -1569,7 +1574,7 @@ abort_accept_claim( Resource* rip, Stream* stream )
 
 
 bool
-accept_request_claim( Resource* rip, Claim* leftover_claim, bool and_pair )
+accept_request_claim( Resource* rip, bool secure_claim_id, Claim* leftover_claim, bool and_pair )
 {
 	int interval = -1;
 	char *client_addr = NULL;
@@ -1593,18 +1598,22 @@ accept_request_claim( Resource* rip, Claim* leftover_claim, bool and_pair )
 		Reply of 4 (REQUEST_CLAIM_PAIR) means claim accepted by a slot
 		  that is paired, and the partner slot ad and claim id will be
 		  sent next.
+		Reply of 5 (REQUEST_CLAIM_LEFTOVERS_2) is the same as 3, but
+		  the claim id is encrypted.
+		Reply of 6 (REQUEST_CLAIM_PAIR_2) is the same as 4, but
+		  the claim id is encrypted.
 	*/
 	int cmd = OK;
 	if ( leftover_claim && leftover_claim->id() && 
 		 leftover_claim->rip()->r_classad ) 
 	{
-		// schedd wants leftovers, send reply code 3
-		cmd = REQUEST_CLAIM_LEFTOVERS;
+		// schedd wants leftovers, send reply code 3 (or 5)
+		cmd = secure_claim_id ? REQUEST_CLAIM_LEFTOVERS_2 : REQUEST_CLAIM_LEFTOVERS;
 	}
 	else if (rip->r_pair_name) {
 		ripb = resmgr->get_by_name(rip->r_pair_name);
 		if (ripb && and_pair) {
-			cmd = REQUEST_CLAIM_PAIR;
+			cmd = secure_claim_id ? REQUEST_CLAIM_PAIR_2 : REQUEST_CLAIM_PAIR;
 		}
 	}
 
@@ -1616,7 +1625,7 @@ accept_request_claim( Resource* rip, Claim* leftover_claim, bool and_pair )
 		abort_accept_claim( rip, stream );
 		return false;
 	}
-	if ( cmd == REQUEST_CLAIM_LEFTOVERS )
+	if ( cmd == REQUEST_CLAIM_LEFTOVERS || cmd == REQUEST_CLAIM_LEFTOVERS_2 )
 	{
 		// schedd just claimed a dynamic slot, and it wants
 		// us to send back to the classad and the new claim id for
@@ -1625,7 +1634,7 @@ accept_request_claim( Resource* rip, Claim* leftover_claim, bool and_pair )
 
 		leftover_claim->rip()->r_classad->Assign(ATTR_LAST_SLOT_NAME, rip->r_name);
 		MyString claimId(leftover_claim->id());
-		if ( !stream->put(claimId) ||
+		if ( !(secure_claim_id ? stream->put_secret(claimId.c_str()) : stream->put(claimId)) ||
 			 !putClassAd(stream, *leftover_claim->rip()->r_classad) )
 		{
 			rip->dprintf( D_ALWAYS, 
@@ -1634,14 +1643,15 @@ accept_request_claim( Resource* rip, Claim* leftover_claim, bool and_pair )
 			return false;
 		}
 	}
-	else if (cmd == REQUEST_CLAIM_PAIR)
+	else if (cmd == REQUEST_CLAIM_PAIR || cmd == REQUEST_CLAIM_PAIR_2)
 	{
 		dprintf(D_FULLDEBUG,"Sending paired slot claim to schedd\n");
 		//PRAGMA_REMIND("remove these next two dprintfs later")
 		//dprintf(D_FULLDEBUG,"\tmain slot claim id is %s\n", rip->r_cur->id());
 		//dprintf(D_FULLDEBUG,"\tpaired slot claim id is %s\n", ripb->r_cur->id());
 		MyString claimId(ripb->r_cur->id());
-		if ( !stream->put(claimId) || ! putClassAd(stream, *ripb->r_classad)) {
+		if ( !(secure_claim_id ? stream->put_secret(claimId.c_str()) : stream->put(claimId)) ||
+		     ! putClassAd(stream, *ripb->r_classad)) {
 			rip->dprintf( D_ALWAYS,
 				"Can't send paired slot claim & ad to schedd.\n" );
 			abort_accept_claim( rip, stream );
diff --git a/src/condor_startd.V6/command.h b/src/condor_startd.V6/command.h
index 540c85d..02eb3f3 100644
--- a/src/condor_startd.V6/command.h
+++ b/src/condor_startd.V6/command.h
@@ -118,7 +118,7 @@ int match_info( Resource*, char* );
 int request_claim( Resource*, Claim *, char*, Stream* ); 
 
 // Accept claim from schedd agent
-bool accept_request_claim( Resource* , Claim * = NULL, bool and_pair = false );
+bool accept_request_claim( Resource* , bool secure_claim_id = true, Claim * = NULL, bool and_pair = false );
 
 // Activate a claim with a given starter
 int activate_claim( Resource*, Stream* ); 
diff --git a/src/condor_starter.V6.1/baseStarter.cpp b/src/condor_starter.V6.1/baseStarter.cpp
index 0cd8062..028bea5 100644
--- a/src/condor_starter.V6.1/baseStarter.cpp
+++ b/src/condor_starter.V6.1/baseStarter.cpp
@@ -3693,7 +3693,7 @@ CStarter::WriteAdFiles()
 		}
 		else
 		{
-			fPrintAd(fp, *ad, true);
+			fPrintAd(fp, *ad);
 			fclose(fp);
 		}
 	}
@@ -3718,7 +3718,7 @@ CStarter::WriteAdFiles()
 		}
 		else
 		{
-			fPrintAd(fp, *ad, true);
+			fPrintAd(fp, *ad);
 			fclose(fp);
 		}
 	}
diff --git a/src/condor_status.V6/prettyPrint.cpp b/src/condor_status.V6/prettyPrint.cpp
index 9489492..c9cc29c 100644
--- a/src/condor_status.V6/prettyPrint.cpp
+++ b/src/condor_status.V6/prettyPrint.cpp
@@ -477,7 +477,7 @@ void prettyPrintAd(ppOption pps, ClassAd *ad, int output_index, StringList * whi
 		classad::References attrs;
 		classad::References *proj = NULL;
 		if (PP_IS_LONGish(pps) && ( ! fHashOrder || whitelist)) {
-			sGetAdAttrs(attrs, *ad, false, whitelist);
+			sGetAdAttrs(attrs, *ad, true, whitelist);
 			proj = &attrs;
 		}
 
diff --git a/src/condor_tools/history.cpp b/src/condor_tools/history.cpp
index f841f34..75cc574 100644
--- a/src/condor_tools/history.cpp
+++ b/src/condor_tools/history.cpp
@@ -743,7 +743,7 @@ main(int argc, char* argv[])
 	ad.InsertAttr(ATTR_OWNER, 1);
 	ad.InsertAttr("StreamResults", true);
 	dprintf(D_FULLDEBUG, "condor_history: sending streaming ACK header ad:\n");
-	dPrintAd(D_FULLDEBUG, ad, false);
+	dPrintAd(D_FULLDEBUG, ad);
 	if ( ! putClassAd(socks[0], ad) || ! socks[0]->end_of_message()) {
 		dprintf(D_ALWAYS, "condor_history: Failed to write streaming ACK header ad\n");
 		exit(1);
@@ -768,7 +768,7 @@ main(int argc, char* argv[])
 	ad.InsertAttr("MalformedAds", writetosocket_failcount);
 	ad.InsertAttr("AdCount", adCount);
 	dprintf(D_FULLDEBUG, "condor_history: sending final ad:\n");
-	dPrintAd(D_FULLDEBUG, ad, false);
+	dPrintAd(D_FULLDEBUG, ad);
 	if ( ! putClassAd(socks[0], ad) || ! socks[0]->end_of_message()) {
 		dprintf(D_ALWAYS, "condor_history: Failed to write final ad to client\n");
 		exit(1);
diff --git a/src/condor_tools/transform_ads.cpp b/src/condor_tools/transform_ads.cpp
index 5224e9c..5f9160f 100644
--- a/src/condor_tools/transform_ads.cpp
+++ b/src/condor_tools/transform_ads.cpp
@@ -1740,8 +1740,6 @@ bool ReportSuccess(const ClassAd * job, apply_transform_args & xform_args)
 	if ( ! job) return false;
 	if (testing.no_output) return true;
 
-	StringList * whitelist = NULL;
-
 	// if we have not yet picked and output format, do that now.
 	if (DashOutFormat == ClassAdFileParseType::Parse_auto) {
 		if (xform_args.input_helper) {
@@ -1759,7 +1757,7 @@ bool ReportSuccess(const ClassAd * job, apply_transform_args & xform_args)
 	classad::References attrs;
 	classad::References *print_order = NULL;
 	if ( ! DashOutAttrsInHashOrder) {
-		sGetAdAttrs(attrs, *job, false, whitelist);
+		sGetAdAttrs(attrs, *job);
 		print_order = &attrs;
 	}
 	switch (DashOutFormat) {
diff --git a/src/condor_utils/compat_classad.cpp b/src/condor_utils/compat_classad.cpp
index 3fed02e..ca9fafa 100644
--- a/src/condor_utils/compat_classad.cpp
+++ b/src/condor_utils/compat_classad.cpp
@@ -1731,7 +1731,7 @@ int CondorClassAdListWriter::appendAd(const ClassAd & ad, std::string & output,
 	classad::References attrs;
 	classad::References *print_order = NULL;
 	if ( ! hash_order || whitelist) {
-		sGetAdAttrs(attrs, ad, false, whitelist);
+		sGetAdAttrs(attrs, ad, true, whitelist);
 		print_order = &attrs;
 	}
 
@@ -2574,7 +2574,12 @@ fPrintAd( FILE *file, const classad::ClassAd &ad, bool exclude_private, StringLi
 {
 	MyString buffer;
 
-	sPrintAd( buffer, ad, exclude_private, attr_white_list );
+	if( exclude_private ) {
+		sPrintAd( buffer, ad, attr_white_list );
+	} else {
+		sPrintAdWithSecrets( buffer, ad, attr_white_list );
+	}
+
 	if ( fprintf(file, "%s", buffer.Value()) < 0 ) {
 		return FALSE;
 	} else {
@@ -2588,14 +2593,19 @@ dPrintAd( int level, const classad::ClassAd &ad, bool exclude_private )
 	if ( IsDebugCatAndVerbosity( level ) ) {
 		MyString buffer;
 
-		sPrintAd( buffer, ad, exclude_private );
+		if( exclude_private ) {
+			sPrintAd( buffer, ad );
+		} else {
+			sPrintAdWithSecrets( buffer, ad );
+		}
 
 		dprintf( level|D_NOHEADER, "%s", buffer.Value() );
 	}
 }
 
+
 int
-sPrintAd( MyString &output, const classad::ClassAd &ad, bool exclude_private, StringList *attr_white_list )
+_sPrintAd( MyString &output, const classad::ClassAd &ad, bool exclude_private, StringList *attr_white_list )
 {
 	classad::ClassAd::const_iterator itr;
 
@@ -2640,10 +2650,30 @@ sPrintAd( MyString &output, const classad::ClassAd &ad, bool exclude_private, St
 }
 
 int
-sPrintAd( std::string &output, const classad::ClassAd &ad, bool exclude_private, StringList *attr_white_list )
+sPrintAd( MyString &output, const classad::ClassAd &ad, StringList *attr_white_list ) {
+	return _sPrintAd( output, ad, true, attr_white_list );
+}
+
+int
+sPrintAdWithSecrets( MyString &output, const classad::ClassAd &ad, StringList *attr_white_list ) {
+	return _sPrintAd( output, ad, false, attr_white_list );
+}
+
+
+int
+sPrintAd( std::string &output, const classad::ClassAd &ad, StringList *attr_white_list )
+{
+	MyString myout;
+	int rc = sPrintAd( myout, ad, attr_white_list );
+	output += myout;
+	return rc;
+}
+
+int
+sPrintAdWithSecrets( std::string &output, const classad::ClassAd &ad, StringList *attr_white_list )
 {
 	MyString myout;
-	int rc = sPrintAd( myout, ad, exclude_private, attr_white_list );
+	int rc = sPrintAdWithSecrets( myout, ad, attr_white_list );
 	output += myout;
 	return rc;
 }
diff --git a/src/condor_utils/compat_classad.h b/src/condor_utils/compat_classad.h
index 15afd8a..33d41e5 100644
--- a/src/condor_utils/compat_classad.h
+++ b/src/condor_utils/compat_classad.h
@@ -58,7 +58,7 @@ typedef std::set<std::string, classad::CaseIgnLTStr> AttrNameSet;
 		@param file The file handle to print to.
 		@return TRUE
 	*/
-int	fPrintAd(FILE *file, const classad::ClassAd &ad, bool exclude_private = false, StringList *attr_white_list = NULL);
+int	fPrintAd(FILE *file, const classad::ClassAd &ad, bool exclude_private = true, StringList *attr_white_list = NULL);
 
 	/** Print the ClassAd as an old ClasAd with dprintf
 		@param level The dprintf level.
@@ -69,13 +69,15 @@ void dPrintAd( int level, const classad::ClassAd &ad, bool exclude_private = tru
 		@param output The MyString to write into
 		@return TRUE
 	*/
-int sPrintAd( MyString &output, const classad::ClassAd &ad, bool exclude_private = false, StringList *attr_white_list = NULL );
+int sPrintAd( MyString &output, const classad::ClassAd &ad, StringList *attr_white_list = NULL );
+int sPrintAdWithSecrets( MyString &output, const classad::ClassAd &ad, StringList *attr_white_list = NULL );
 
 	/** Format the ClassAd as an old ClassAd into the std::string.
 		@param output The std::string to write into
 		@return TRUE
 	*/
-int sPrintAd( std::string &output, const classad::ClassAd &ad, bool exclude_private = false, StringList *attr_white_list = NULL );
+int sPrintAd( std::string &output, const classad::ClassAd &ad, StringList *attr_white_list = NULL );
+int sPrintAdWithSecrets( std::string &output, const classad::ClassAd & ad, StringList *attr_white_list = NULL );
 
 	/** Get a sorted list of attributes that are in the given ad, and also match the given whitelist (if any)
 		@param attrs the set of attrs to insert into. This is set is NOT cleared first.
diff --git a/src/condor_utils/file_transfer.cpp b/src/condor_utils/file_transfer.cpp
index 3be2e61..6aab8c3 100644
--- a/src/condor_utils/file_transfer.cpp
+++ b/src/condor_utils/file_transfer.cpp
@@ -3218,7 +3218,13 @@ FileTransfer::DoUpload(filesize_t *total_bytes, ReliSock *s)
 					return_and_resetpriv( -1 );
 				}
 
-				// compute the size of what we sent
+				//
+				// This comment used to read 'compute the size of what we sent',
+				// but obviously the wire format and the string format of
+				// ClassAds are not the same and can't be expected to be the
+				// same length.  Since the size will be wrong anyway, simplify
+				// future security audits but not printing the private attrs.
+				//
 				MyString junkbuf;
 				sPrintAd(junkbuf, file_info);
 				bytes = junkbuf.Length();
diff --git a/src/condor_who/who.cpp b/src/condor_who/who.cpp
index 7be0d66..19f2a04 100644
--- a/src/condor_who/who.cpp
+++ b/src/condor_who/who.cpp
@@ -1464,7 +1464,7 @@ main( int argc, char *argv[] )
 							std::string tmp;
 							if (App.print_mask.IsEmpty()) {
 								classad::References attrs;
-								sGetAdAttrs(attrs, ready_ad, false, NULL);
+								sGetAdAttrs(attrs, ready_ad);
 								sPrintAdAttrs(tmp, ready_ad, attrs);
 							} else {
 								if (App.print_mask.has_headings()) {
@@ -1692,7 +1692,7 @@ main( int argc, char *argv[] )
 			while (ClassAd	*ad = result.Next()) {
 				tmp.clear();
 				classad::References attrs;
-				sGetAdAttrs(attrs, *ad, false, NULL);
+				sGetAdAttrs(attrs, *ad);
 				sPrintAdAttrs(tmp, *ad, attrs);
 				tmp += "\n";
 				fputs(tmp.c_str(), stdout);

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to