Пример #1
0
// This handler is called when a client wishes to write files from the
// transferd's storage.
int
TransferD::write_files_handler(int cmd, Stream *sock) 
{
	ReliSock *rsock = (ReliSock*)sock;
	MyString capability;
	int protocol = FTP_UNKNOWN;
	TransferRequest *treq = NULL;
	MyString fquser;
	static int transfer_reaper_id = -1;
	ThreadArg *thread_arg;
	int tid;
	ClassAd reqad;
	ClassAd respad;

	cmd = cmd; // quiet the compiler.

	dprintf(D_ALWAYS, "Got TRANSFERD_WRITE_FILES!\n");

	/////////////////////////////////////////////////////////////////////////
	// make sure we are authenticated
	/////////////////////////////////////////////////////////////////////////
	if( ! rsock->triedAuthentication() ) {
		CondorError errstack;
		if( ! SecMan::authenticate_sock(rsock, WRITE, &errstack) ) {
			// we failed to authenticate, we should bail out now
			// since we don't know what user is trying to perform
			// this action.
			// TODO: it'd be nice to print out what failed, but we
			// need better error propagation for that...
			errstack.push( "TransferD::setup_transfer_request_handler()", 42,
				"Failure to register transferd - Authentication failed" );
			dprintf( D_ALWAYS, "setup_transfer_request_handler() "
				"aborting: %s\n",
				errstack.getFullText() );
			refuse( rsock );
			return CLOSE_STREAM;
		} 
	}

	fquser = rsock->getFullyQualifiedUser();


	/////////////////////////////////////////////////////////////////////////
	// Check to see if the capability the client tells us is something that
	// we have knowledge of. We ONLY check the capability and not the
	// identity of the person in question. This allows people of different
	// identities to write files here as long as they had the right 
	// capability. While this might not sound secure, they STILL had to have
	// authenticated as someone this daemon trusts. 
	// Similarly, check the protocol it wants to use as well as ensure that
	// the direction the transfer request was supposed to be is being honored.
	/////////////////////////////////////////////////////////////////////////
	rsock->decode();

	// soak the request ad from the client about what it wants to transfer
	reqad.initFromStream(*rsock);
	rsock->end_of_message();

	reqad.LookupString(ATTR_TREQ_CAPABILITY, capability);

	rsock->encode();

	// do I know of such a capability?
	if (m_treqs.lookup(capability, treq) != 0) {
		// didn't find it. Log it and tell them to leave and close up shop
		respad.Assign(ATTR_TREQ_INVALID_REQUEST, TRUE);
		respad.Assign(ATTR_TREQ_INVALID_REASON, "Invalid capability!");
		respad.put(*rsock);
		rsock->end_of_message();

		dprintf(D_ALWAYS, "Client identity '%s' tried to write some files "
			"using capability '%s', but there was no such capability. "
			"Access denied.\n", fquser.Value(), capability.Value());
		return CLOSE_STREAM;
	}

	reqad.LookupInteger(ATTR_TREQ_FTP, protocol);

	// am I willing to use this protocol?
	switch(protocol) {
		case FTP_CFTP: // FileTrans protocol, I'm happy.
			break;

		default:
			respad.Assign(ATTR_TREQ_INVALID_REQUEST, TRUE);
			respad.Assign(ATTR_TREQ_INVALID_REASON, 
				"Invalid file transfer protocol!");
			respad.put(*rsock);
			rsock->end_of_message();

			dprintf(D_ALWAYS, "Client identity '%s' tried to write some files "
				"using protocol '%d', but I don't support that protocol. "
				"Access denied.\n", fquser.Value(), protocol);
			return CLOSE_STREAM;
	}

	// nsure that this transfer request was of the uploading variety
	if (treq->get_direction() != FTPD_UPLOAD) {
			respad.Assign(ATTR_TREQ_INVALID_REQUEST, TRUE);
			respad.Assign(ATTR_TREQ_INVALID_REASON, 
				"Transfer Request was not an uploading request!");
			respad.put(*rsock);
			rsock->end_of_message();

			dprintf(D_ALWAYS, "Client identity '%s' tried to write some files "
				"to a transfer request that wasn't expecting to be written. "
				"Access denied.\n", fquser.Value());
	}

	/////////////////////////////////////////////////////////////////////////
	// Tell the client everything was ok.
	/////////////////////////////////////////////////////////////////////////

	respad.Assign(ATTR_TREQ_INVALID_REQUEST, FALSE);
	respad.put(*rsock);
	rsock->end_of_message();

	/////////////////////////////////////////////////////////////////////////
	// Set up a thread (a process under unix) to read ALL of the job files
	// for all of the ads in the TransferRequest.
	/////////////////////////////////////////////////////////////////////////

	// now create a thread, passing in the sock, which uses the file transfer
	// object to accept the files.

	if (transfer_reaper_id == -1) {
		// only set this up ONCE so each and every thread gets one.
		transfer_reaper_id = daemonCore->Register_Reaper(
						"write_files_reaper",
						(ReaperHandlercpp) &TransferD::write_files_reaper,
						"write_files_reaper",
						this
						);
	}

	thread_arg = new ThreadArg(protocol, treq);

	// Start a new thread (process on Unix) to do the work
	tid = daemonCore->Create_Thread(
		(ThreadStartFunc)&TransferD::write_files_thread,
		(void *)thread_arg,
		rsock,
		transfer_reaper_id
		);
	
	if (tid == FALSE) {
		// XXX How do I handle this failure?
	}


	// associate the tid with the request so I can deal with it propery in
	// the reaper
	m_client_to_transferd_threads.insert(tid, treq);

	// The stream is inherited to the thread, who does the transfer and
	// finishes the protocol, but in the parent, I'm closing it.
	return CLOSE_STREAM;
}
Пример #2
0
int 
store_cred_handler(Service * /*service*/, int /*i*/, Stream *stream) {
  void * data = NULL;
  int rtnVal = FALSE;
  int rc;
  char * temp_file_name = NULL;
  bool found_cred;
  CredentialWrapper * temp_cred = NULL;
  int data_size = -1;
  classad::ClassAd * _classad = NULL;
  classad::ClassAd classad;
  std::string classad_cstr;
  char * classad_str = NULL;
  classad::ClassAdParser parser;
  ReliSock * socket = (ReliSock*)stream;
  const char * user = NULL;

  CredentialWrapper * cred_wrapper = NULL;

  if (!socket->triedAuthentication()) { 
    CondorError errstack;
    if( ! SecMan::authenticate_sock(socket, WRITE, &errstack) ) {
      dprintf (D_ALWAYS, "Unable to authenticate, qutting\n");
      goto EXIT;
    }
  }

  user = socket->getFullyQualifiedUser();
  dprintf (D_FULLDEBUG, "Request by: %s, %s\n", socket->getOwner(), user);

  socket->decode();

  if (!socket->code (classad_str)) {
    dprintf (D_ALWAYS, "Error receiving credential metadata\n"); 
    goto EXIT;
  }

  classad_cstr = classad_str;
  free (classad_str);

  _classad = parser.ParseClassAd(classad_cstr);
  if (!_classad) {
	  dprintf (D_ALWAYS, "Error: invalid credential metadata %s\n", classad_cstr.c_str());
	  goto EXIT;
  }

  classad = *_classad;
  delete _classad;
  
 
  
  int type;
  if (!classad.EvaluateAttrInt ("Type", type)) {
    dprintf (D_ALWAYS, "Missing Type attribute in classad!\n");
    goto EXIT;
  }


  if (type == X509_CREDENTIAL_TYPE) {
	cred_wrapper = new X509CredentialWrapper (classad);
    dprintf (D_ALWAYS, "Name=%s Size=%d\n", 
			 cred_wrapper->cred->GetName(), 
			 cred_wrapper->cred->GetDataSize());

  } else {
	  dprintf (D_ALWAYS, "Unsupported credential type %d\n", type);
	  goto EXIT;
  }

  cred_wrapper->cred->SetOrigOwner (socket->getOwner()); // original remote uname
  cred_wrapper->cred->SetOwner (user);                   // mapped uname

  // Receive credential data
  data_size = cred_wrapper->cred->GetDataSize();
  if (data_size > MAX_CRED_DATA_SIZE) {
	  dprintf (D_ALWAYS, "ERROR: Credential data size %d > maximum allowed (%d)\n", data_size, MAX_CRED_DATA_SIZE);
	  goto EXIT;
  }

  data = malloc (data_size);
  if (data == NULL) {
	  EXCEPT("Out of memory. Aborting.");
  }
  if (!socket->code_bytes(data,data_size)) {
    dprintf (D_ALWAYS, "Error receiving credential data\n");
    goto EXIT;
  }
  cred_wrapper->cred->SetData (data, data_size);
  

  // Check whether credential under this name already exists
  found_cred=false;
  credentials.Rewind();
  while (credentials.Next(temp_cred)) {
	  if ((strcmp(cred_wrapper->cred->GetName(), 
				  temp_cred->cred->GetName()) == 0) && 
		  (strcmp(cred_wrapper->cred->GetOwner(), 
				  temp_cred->cred->GetOwner()) == 0)) {
		  found_cred=true;
		  break; // found it
	  }
  }

  if (found_cred) {
	  dprintf (D_ALWAYS, "Credential %s for owner %s already exists!\n", 
			   cred_wrapper->cred->GetName(), 
			   cred_wrapper->cred->GetOwner());
	  socket->encode();
	  int rcred=CREDD_ERROR_CREDENTIAL_ALREADY_EXISTS;
	  socket->code(rcred);
	  goto EXIT;
  }

  
  // Write data to a file
  temp_file_name = dircat (cred_store_dir, "credXXXXXX");
  condor_mkstemp (temp_file_name);
  cred_wrapper->SetStorageName (temp_file_name);
  
  init_user_id_from_FQN (user);
  if (!StoreData(temp_file_name,data,data_size)) {
    socket->encode();
    int rcred = CREDD_UNABLE_TO_STORE;
    socket->code(rcred);
    goto EXIT;
  }

  ((X509CredentialWrapper*)cred_wrapper)->cred->SetRealExpirationTime (
			   x509_proxy_expiration_time(temp_file_name));

  // Write metadata to a file
  credentials.Append (cred_wrapper);
  SaveCredentialList();

  // Write response to the client
  socket->encode();
  rc = CREDD_SUCCESS;
  socket->code(rc);

  dprintf( D_ALWAYS, "Credential name %s owner %s successfully stored\n",
			 cred_wrapper->cred->GetName(), cred_wrapper->cred->GetOwner() );

  if (type == X509_CREDENTIAL_TYPE) {
	((X509Credential*)cred_wrapper->cred)->display( D_FULLDEBUG );
  }
  rtnVal = TRUE;

EXIT:
  if ( data != NULL ) {
	  free (data);
  }
  if ( temp_file_name != NULL ) {
	  delete [] temp_file_name;
  }
  if ( cred_wrapper != NULL) {
	  delete cred_wrapper;
  }
  return rtnVal;
}
Пример #3
0
int 
query_cred_handler(Service * /*service*/, int /*i*/, Stream *stream) {

  classad::ClassAdUnParser unparser;
  std::string adbuffer;

  char * request = NULL;
  int rtnVal = FALSE;
  int length;
  CredentialWrapper * cred = NULL;
  SimpleList <Credential*> result_list;

  ReliSock * socket = (ReliSock*)stream;
  const char * user;


  if (!socket->triedAuthentication()) {
    CondorError errstack;
    if( ! SecMan::authenticate_sock(socket, READ, &errstack) ) {
      dprintf (D_ALWAYS, "Unable to authenticate, qutting\n");
      goto EXIT;
    }
  }
  user = socket->getFullyQualifiedUser();
  dprintf (D_ALWAYS, "Authenticated as %s\n", user);


  socket->decode();
  if (!socket->code(request)) {
    dprintf (D_ALWAYS, "Error receiving request\n"); 
    goto EXIT;
  }

  if ((request != NULL) && (strcmp (request, "*") == 0)) {
      if (!isSuperUser (user)) {
	dprintf (D_ALWAYS, "User %s is NOT super user, request DENIED\n", user);
    goto EXIT;
    }
  }

    
  // Find credentials for this user
  credentials.Rewind();
  while (credentials.Next(cred)) {
	  if (cred->cred->GetType() == X509_CREDENTIAL_TYPE) {
		  if (strcmp(cred->cred->GetOwner(), user) == 0) {
			  result_list.Append (cred->cred);
		  }
	  }
  }



  socket->encode();
  length = result_list.Length();
  dprintf (D_FULLDEBUG, "User has %d credentials\n", length);
  socket->code (length);
	

  Credential * _cred;
  result_list.Rewind();
  while (result_list.Next(_cred)) {
	  classad::ClassAd * _temp = cred->GetMetadata();
	  unparser.Unparse(adbuffer,_temp);
	  char * classad_str = strdup(adbuffer.c_str());
	  socket->code (classad_str);
	  free (classad_str);
	  delete _temp;
  }
  rtnVal = TRUE;
  
EXIT:
  if (request != NULL) {
	  free (request);
  }
  return rtnVal;
}
Пример #4
0
int 
rm_cred_handler(Service * /*service*/, int /*i*/, Stream *stream) {
  char * name = NULL;
  int rtnVal = FALSE;
  int rc;
  bool found_cred;
  CredentialWrapper * cred_wrapper = NULL;
  char * owner = NULL;
  const char * user;

  ReliSock * socket = (ReliSock*)stream;

  if (!socket->triedAuthentication()) {
    CondorError errstack;
    if( ! SecMan::authenticate_sock(socket, READ, &errstack) ) {
      dprintf (D_ALWAYS, "Unable to authenticate, qutting\n");
      goto EXIT;
    }
  }


  socket->decode();

  if (!socket->code(name)) {
    dprintf (D_ALWAYS, "Error receiving credential name\n"); 
    goto EXIT;
  }

  user = socket->getFullyQualifiedUser();

  dprintf (D_ALWAYS, "Authenticated as %s\n", user);

  if (strchr (name, ':')) {
    // The name is of the form user:name
    // This better be a super-user!
    // TODO: Check super-user's list

    // Owner is the first part
    owner = strdup (name);
    char * pColon = strchr (owner, ':');
    *pColon = '\0';
    
    // Name is the second part
    sprintf (name, "%s", (char*)(pColon+sizeof(char)));
  
    if (strcmp (owner, user) != 0) { 
      dprintf (D_ALWAYS, "Requesting another user's (%s) credential %s\n", owner, name);

      if (!isSuperUser (user)) {
	dprintf (D_ALWAYS, "User %s is NOT super user, request DENIED\n", user);
	goto EXIT;
      } else {
	dprintf (D_FULLDEBUG, "User %s is super user, request GRANTED\n", user);
      }
    }

  } else {
    owner = strdup (user);
  }

  dprintf (D_ALWAYS, "Attempting to delete cred %s for user %s\n", name, owner);
  

  found_cred=false;
  credentials.Rewind();
  while (credentials.Next(cred_wrapper)) {
	  if (cred_wrapper->cred->GetType() == X509_CREDENTIAL_TYPE) {
		  if ((strcmp(cred_wrapper->cred->GetName(), name) == 0) && 
			  (strcmp(cred_wrapper->cred->GetOwner(), owner) == 0)) {
			  credentials.DeleteCurrent();
			  found_cred=true;
			  break; // found it
		  }
	  }
  }


  if (found_cred) {
    priv_state priv = set_root_priv();
    // Remove credential data
    unlink (cred_wrapper->GetStorageName());
    // Save the metadata list
    SaveCredentialList();
    set_priv(priv);
    delete cred_wrapper;
    dprintf (D_ALWAYS, "Removed credential %s for owner %s\n", name, owner);
  } else {
    dprintf (D_ALWAYS, "Unable to remove credential %s:%s (not found)\n", owner, name); 
  }
	    
  
  free (owner);
  
  socket->encode();
 

  rc = (found_cred)?CREDD_SUCCESS:CREDD_CREDENTIAL_NOT_FOUND;
  socket->code(rc);

  rtnVal = TRUE;

EXIT:
  if (name != NULL) {
	  free (name);
  }
  return rtnVal;
}
Пример #5
0
int 
get_cred_handler(Service * /*service*/, int /*i*/, Stream *stream) {
  char * name = NULL;
  int rtnVal = FALSE;
  bool found_cred=false;
  CredentialWrapper * cred = NULL;
  char * owner = NULL;
  const char * user = NULL;
  void * data = NULL;

  ReliSock * socket = (ReliSock*)stream;

  // Authenticate
  if (!socket->triedAuthentication()) {
    CondorError errstack;
    if( ! SecMan::authenticate_sock(socket, READ, &errstack) ) {
      dprintf (D_ALWAYS, "Unable to authenticate, qutting\n");
      goto EXIT;
    }
  }

  socket->decode();

  if (!socket->code(name)) {
    dprintf (D_ALWAYS, "Error receiving credential name\n"); 
    goto EXIT;
  }

  user = socket->getFullyQualifiedUser();
  dprintf (D_ALWAYS, "Authenticated as %s\n", user);

  if (strchr (name, ':')) {
    // The name is of the form user:name
    // This better be a super-user!
    // TODO: Check super-user's list

    // Owner is the first part
    owner = strdup (name);
    char * pColon = strchr (owner, ':');
    *pColon = '\0';
    
    // Name is the second part
    sprintf (name, "%s", (char*)(pColon+sizeof(char)));
  
    if (strcmp (owner, user) != 0) { 
      dprintf (D_ALWAYS, "Requesting another user's (%s) credential %s\n", owner, name);

      if (!isSuperUser (user)) {
	dprintf (D_ALWAYS, "User %s is NOT super user, request DENIED\n", user);
	goto EXIT;
      } else {
	dprintf (D_FULLDEBUG, "User %s is super user, request GRANTED\n", user);
      }
    }

  } else {
    owner = strdup (user);
  }

  dprintf (D_ALWAYS, "sending cred %s for user %s\n", name, owner);

  credentials.Rewind();
  while (credentials.Next(cred)) {
	  if (cred->cred->GetType() == X509_CREDENTIAL_TYPE) {
		  if ((strcmp(cred->cred->GetName(), name) == 0) && 
			  (strcmp(cred->cred->GetOwner(), owner) == 0)) {
			  found_cred=true;
			  break; // found it
      }
    }
  }
  
  socket->encode();

  if (found_cred) {
    dprintf (D_FULLDEBUG, "Found cred %s\n", cred->GetStorageName());
    
    int data_size;

    
    int rc = LoadData (cred->GetStorageName(), data, data_size);
    dprintf (D_FULLDEBUG, "Credential::LoadData returned %d\n", rc);
    if (rc == 0) {
      goto EXIT;
    }
    
    socket->code (data_size);
    socket->code_bytes (data, data_size);
    dprintf (D_ALWAYS, "Credential name %s for owner %s returned to user %s\n",
			name, owner, user);
  }
  else {
    dprintf (D_ALWAYS, "Cannot find cred %s\n", name);
    int rc = CREDD_CREDENTIAL_NOT_FOUND;
    socket->code (rc);
  }

  rtnVal = TRUE;
EXIT:
  if ( name != NULL) {
	  free (name);
  }
  if ( owner != NULL) {
	  free (owner);
  }
  if ( data != NULL) {
	  free (data);
  }
  return rtnVal;
}