/****************************************************************************
change status of a printer queue entry
****************************************************************************/
void status_printjob(int cnum,int snum,int jobid,int status)
{
  char *lpstatus_command = 
    (status==LPQ_PAUSED?lp_lppausecommand(snum):lp_lpresumecommand(snum));
  char *printername = PRINTERNAME(snum);
  pstring syscmd;
  char jobstr[20];
  int ret;

  if (!printername || !*printername)
    {
      DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n",
	    lp_servicename(snum),snum));
      printername = lp_servicename(snum);
    }
    
  if (!lpstatus_command || !(*lpstatus_command))
    {
      DEBUG(5,("No lpstatus command to %s job\n",
	       (status==LPQ_PAUSED?"pause":"resume")));
      return;
    }
    
  slprintf(jobstr,sizeof(jobstr)-1,"%d",jobid);

  pstrcpy(syscmd,lpstatus_command);
  string_sub(syscmd,"%p",printername);
  string_sub(syscmd,"%j",jobstr);
  standard_sub(cnum,syscmd);

  ret = smbrun(syscmd,NULL,False);
  DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));  
  lpq_reset(snum); /* queue has changed */
}
/****************************************************************************
delete a printer queue entry
****************************************************************************/
void del_printqueue(int cnum,int snum,int jobid)
{
  char *lprm_command = lp_lprmcommand(snum);
  char *printername = PRINTERNAME(snum);
  pstring syscmd;
  char jobstr[20];
  int ret;

  if (!printername || !*printername)
    {
      DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n",
	    lp_servicename(snum),snum));
      printername = lp_servicename(snum);
    }
    
  if (!lprm_command || !(*lprm_command))
    {
      DEBUG(5,("No lprm command\n"));
      return;
    }
    
  slprintf(jobstr,sizeof(jobstr)-1,"%d",jobid);

  pstrcpy(syscmd,lprm_command);
  string_sub(syscmd,"%p",printername);
  string_sub(syscmd,"%j",jobstr);
  standard_sub(cnum,syscmd);

  ret = smbrun(syscmd,NULL,False);
  DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));  
  lpq_reset(snum); /* queue has changed */
}
/****************************************************************************
Build the print command in the supplied buffer. This means getting the
print command for the service and inserting the printer name and the
print file name. Return NULL on error, else the passed buffer pointer.
****************************************************************************/
static char *build_print_command(int cnum, char *command, char *syscmd, char *filename1)
{
  int snum = SNUM(cnum);
  char *tstr;
  pstring filename;
  
  /* get the print command for the service. */
  tstr = command;
  if (!syscmd || !tstr) {
    DEBUG(0,("No print command for service `%s'\n", SERVICE(snum)));
    return (NULL);
  }

  /* copy the command into the buffer for extensive meddling. */
  StrnCpy(syscmd, tstr, sizeof(pstring) - 1);
  
  /* look for "%s" in the string. If there is no %s, we cannot print. */   
  if (!strstr(syscmd, "%s") && !strstr(syscmd, "%f")) {
    DEBUG(2,("WARNING! No placeholder for the filename in the print command for service %s!\n", SERVICE(snum)));
  }
  
  if (strstr(syscmd,"%s")) {
    int iOffset = PTR_DIFF(strstr(syscmd, "%s"),syscmd);
    
    /* construct the full path for the filename, shouldn't be necessary unless
       the subshell causes a "cd" to be executed.
       Only use the full path if there isn't a / preceding the %s */
    if (iOffset==0 || syscmd[iOffset-1] != '/') {
      StrnCpy(filename,Connections[cnum].connectpath,sizeof(filename)-1);
      trim_string(filename,"","/");
      pstrcat(filename,"/");
      pstrcat(filename,filename1);
    }
    else
      pstrcpy(filename,filename1);
    
    string_sub(syscmd, "%s", filename);
  }
  
  string_sub(syscmd, "%f", filename1);
  
  /* Does the service have a printername? If not, make a fake and empty    */
  /* printer name. That way a %p is treated sanely if no printer */
  /* name was specified to replace it. This eventuality is logged.         */
  tstr = PRINTERNAME(snum);
  if (tstr == NULL || tstr[0] == '\0') {
    DEBUG(3,( "No printer name - using %s.\n", SERVICE(snum)));
    tstr = SERVICE(snum);
  }
  
  string_sub(syscmd, "%p", tstr);
  
  standard_sub(cnum,syscmd);
  
  return (syscmd);
}
Exemple #4
0
/****************************************************************************
close a cnum
****************************************************************************/
void close_cnum(connection_struct *conn, uint16 vuid)
{
	DirCacheFlush(SNUM(conn));

	unbecome_user();

	DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
				 remote_machine,conn->client_address,
				 lp_servicename(SNUM(conn))));

	yield_connection(conn,
			 lp_servicename(SNUM(conn)),
			 lp_max_connections(SNUM(conn)));

	if (lp_status(SNUM(conn)))
		yield_connection(conn,"STATUS.",MAXSTATUS);

	file_close_conn(conn);
	dptr_closecnum(conn);

	/* execute any "postexec = " line */
	if (*lp_postexec(SNUM(conn)) && 
	    become_user(conn, vuid))  {
		pstring cmd;
		pstrcpy(cmd,lp_postexec(SNUM(conn)));
		standard_sub(conn,cmd);
		smbrun(cmd,NULL,False);
		unbecome_user();
	}

	unbecome_user();
	/* execute any "root postexec = " line */
	if (*lp_rootpostexec(SNUM(conn)))  {
		pstring cmd;
		pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
		standard_sub(conn,cmd);
		smbrun(cmd,NULL,False);
	}
	
	conn_free(conn);
}
/****************************************************************************
get a printer queue
****************************************************************************/
int get_printqueue(int snum,int cnum,print_queue_struct **queue,
		   print_status_struct *status)
{
  char *lpq_command = lp_lpqcommand(snum);
  char *printername = PRINTERNAME(snum);
  int ret=0,count=0;
  pstring syscmd;
  fstring outfile;
  pstring line;
  FILE *f;
  struct stat sbuf;
  BOOL dorun=True;
  int cachetime = lp_lpqcachetime();

  *line = 0;
  check_lpq_cache(snum);
  
  if (!printername || !*printername)
    {
      DEBUG(6,("xx replacing printer name with service (snum=(%s,%d))\n",
	       lp_servicename(snum),snum));
      printername = lp_servicename(snum);
    }
    
  if (!lpq_command || !(*lpq_command))
    {
      DEBUG(5,("No lpq command\n"));
      return(0);
    }
    
  pstrcpy(syscmd,lpq_command);
  string_sub(syscmd,"%p",printername);

  standard_sub(cnum,syscmd);

  slprintf(outfile,sizeof(outfile)-1, "%s/lpq.%08x",tmpdir(),str_checksum(syscmd));
  
  if (!lpq_cache_reset[snum] && cachetime && !stat(outfile,&sbuf)) 
    {
      if (time(NULL) - sbuf.st_mtime < cachetime) {
	DEBUG(3,("Using cached lpq output\n"));
	dorun = False;
      }
    }

  if (dorun) {
    ret = smbrun(syscmd,outfile,True);
    DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
  }

  lpq_cache_reset[snum] = False;

  f = fopen(outfile,"r");
  if (!f) {
    return(0);
  }

  if (status) {
    fstrcpy(status->message,"");
    status->status = LPSTAT_OK;
  }
      
  while (fgets(line,sizeof(pstring),f))
    {
      DEBUG(6,("QUEUE2: %s\n",line));

      *queue = Realloc(*queue,sizeof(print_queue_struct)*(count+1));
      if (! *queue)
	{
	  count = 0;
	  break;
	}

      bzero((char *)&(*queue)[count],sizeof(**queue));
	  
      /* parse it */
      if (!parse_lpq_entry(snum,line,&(*queue)[count],status,count==0))
	continue;
	  
      count++;
    }	      

  fclose(f);

  if (!cachetime) {
    unlink(outfile);
  } else {
    /* we only expect this to succeed on trapdoor systems, on normal systems
     the file is owned by root */
    chmod(outfile,0666);
  }
  return(count);
}
Exemple #6
0
/****************************************************************************
  make a connection to a service
****************************************************************************/
connection_struct *make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid, int *ecode)
{
	int snum;
	struct passwd *pass = NULL;
	BOOL guest = False;
	BOOL force = False;
	extern int Client;
	connection_struct *conn;
	int ret;

	strlower(service);

	snum = find_service(service);
	if (snum < 0) {
		extern int Client;
		if (strequal(service,"IPC$")) {
			DEBUG(3,("refusing IPC connection\n"));
			*ecode = ERRnoipc;
			return NULL;
		}

		DEBUG(0,("%s (%s) couldn't find service %s\n",
			 remote_machine, client_addr(Client), service));
		*ecode = ERRinvnetname;
		return NULL;
	}

	if (strequal(service,HOMES_NAME)) {
		if (*user && Get_Pwnam(user,True)) {
			fstring dos_username;
			fstrcpy(dos_username, user);
			unix_to_dos(dos_username, True);
			return(make_connection(dos_username,user,password,
					       pwlen,dev,vuid,ecode));
		}

		if(lp_security() != SEC_SHARE) {
			if (validated_username(vuid)) {
				fstring dos_username;
				fstrcpy(user,validated_username(vuid));
				fstrcpy(dos_username, user);
				unix_to_dos(dos_username, True);
				return(make_connection(dos_username,user,password,pwlen,dev,vuid,ecode));
			}
		} else {
			/* Security = share. Try with sesssetup_user
			 * as the username.  */
			if(*sesssetup_user) {
				fstring dos_username;
				fstrcpy(user,sesssetup_user);
				fstrcpy(dos_username, user);
				unix_to_dos(dos_username, True);
				return(make_connection(dos_username,user,password,pwlen,dev,vuid,ecode));
			}
		}
	}

	if (!lp_snum_ok(snum) || 
	    !check_access(Client, 
			  lp_hostsallow(snum), lp_hostsdeny(snum))) {    
		*ecode = ERRaccess;
		return NULL;
	}

	/* you can only connect to the IPC$ service as an ipc device */
	if (strequal(service,"IPC$"))
		pstrcpy(dev,"IPC");
	
	if (*dev == '?' || !*dev) {
		if (lp_print_ok(snum)) {
			pstrcpy(dev,"LPT1:");
		} else {
			pstrcpy(dev,"A:");
		}
	}

	/* if the request is as a printer and you can't print then refuse */
	strupper(dev);
	if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
		DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
		*ecode = ERRinvdevice;
		return NULL;
	}

	/* lowercase the user name */
	strlower(user);

	/* add it as a possible user name */
	add_session_user(service);

	/* shall we let them in? */
	if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid)) {
		DEBUG( 2, ( "Invalid username/password for %s\n", service ) );
		*ecode = ERRbadpw;
		return NULL;
	}
  
	conn = conn_new();
	if (!conn) {
		DEBUG(0,("Couldn't find free connection.\n"));
		*ecode = ERRnoresource;
		conn_free(conn);
		return NULL;
	}

	/* find out some info about the user */
	pass = Get_Pwnam(user,True);

	if (pass == NULL) {
		DEBUG(0,( "Couldn't find account %s\n",user));
		*ecode = ERRbaduid;
		conn_free(conn);
		return NULL;
	}

	conn->read_only = lp_readonly(snum);

	{
		pstring list;
		StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
		pstring_sub(list,"%S",service);

		if (user_in_list(user,list))
			conn->read_only = True;
		
		StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
		pstring_sub(list,"%S",service);
		
		if (user_in_list(user,list))
			conn->read_only = False;    
	}

	/* admin user check */
	
	/* JRA - original code denied admin user if the share was
	   marked read_only. Changed as I don't think this is needed,
	   but old code left in case there is a problem here.
	*/
	if (user_in_list(user,lp_admin_users(snum)) 
#if 0
	    && !conn->read_only
#endif
	    ) {
		conn->admin_user = True;
		DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
	} else {
		conn->admin_user = False;
	}
    
	conn->force_user = force;
	conn->vuid = vuid;
	conn->uid = pass->pw_uid;
	conn->gid = pass->pw_gid;
	safe_strcpy(conn->client_address, client_addr(Client), sizeof(conn->client_address)-1);
	conn->num_files_open = 0;
	conn->lastused = time(NULL);
	conn->service = snum;
	conn->used = True;
	conn->printer = (strncmp(dev,"LPT",3) == 0);
	conn->ipc = (strncmp(dev,"IPC",3) == 0);
	conn->dirptr = NULL;
	conn->veto_list = NULL;
	conn->hide_list = NULL;
	conn->veto_oplock_list = NULL;
	string_set(&conn->dirpath,"");
	string_set(&conn->user,user);
	
	/*
	 * If force user is true, then store the
	 * given userid and also the primary groupid
	 * of the user we're forcing.
	 */
	
	if (*lp_force_user(snum)) {
		struct passwd *pass2;
		pstring fuser;
		pstrcpy(fuser,lp_force_user(snum));

		/* Allow %S to be used by force user. */
		pstring_sub(fuser,"%S",service);

		pass2 = (struct passwd *)Get_Pwnam(fuser,True);
		if (pass2) {
			conn->uid = pass2->pw_uid;
			conn->gid = pass2->pw_gid;
			string_set(&conn->user,fuser);
			fstrcpy(user,fuser);
			conn->force_user = True;
			DEBUG(3,("Forced user %s\n",fuser));	  
		} else {
			DEBUG(1,("Couldn't find user %s\n",fuser));
		}
	}

#ifdef HAVE_GETGRNAM 
	/*
	 * If force group is true, then override
	 * any groupid stored for the connecting user.
	 */
	
	if (*lp_force_group(snum)) {
		struct group *gptr;
		pstring gname;
		pstring tmp_gname;
		BOOL user_must_be_member = False;
		
		StrnCpy(tmp_gname,lp_force_group(snum),sizeof(pstring)-1);

		if (tmp_gname[0] == '+') {
			user_must_be_member = True;
			StrnCpy(gname,&tmp_gname[1],sizeof(pstring)-2);
		} else {
			StrnCpy(gname,tmp_gname,sizeof(pstring)-1);
		}
		/* default service may be a group name 		*/
		pstring_sub(gname,"%S",service);
		gptr = (struct group *)getgrnam(gname);
		
		if (gptr) {
			/*
			 * If the user has been forced and the forced group starts
			 * with a '+', then we only set the group to be the forced
			 * group if the forced user is a member of that group.
			 * Otherwise, the meaning of the '+' would be ignored.
			 */
			if (conn->force_user && user_must_be_member) {
				int i;
				for (i = 0; gptr->gr_mem[i] != NULL; i++) {
					if (strcmp(user,gptr->gr_mem[i]) == 0) {
						conn->gid = gptr->gr_gid;
						DEBUG(3,("Forced group %s for member %s\n",gname,user));
						break;
					}
				}
			} else {
				conn->gid = gptr->gr_gid;
				DEBUG(3,("Forced group %s\n",gname));
			}
		} else {
			DEBUG(1,("Couldn't find group %s\n",gname));
		}
	}
#endif /* HAVE_GETGRNAM */

	{
		pstring s;
		pstrcpy(s,lp_pathname(snum));
		standard_sub(conn,s);
		string_set(&conn->connectpath,s);
		DEBUG(3,("Connect path is %s\n",s));
	}

	/* groups stuff added by ih */
	conn->ngroups = 0;
	conn->groups = NULL;
	
	if (!IS_IPC(conn)) {
		/* Find all the groups this uid is in and
		   store them. Used by become_user() */
		setup_groups(conn->user,conn->uid,conn->gid,
			     &conn->ngroups,&conn->groups);
		
		/* check number of connections */
		if (!claim_connection(conn,
				      lp_servicename(SNUM(conn)),
				      lp_max_connections(SNUM(conn)),
				      False)) {
			DEBUG(1,("too many connections - rejected\n"));
			*ecode = ERRnoresource;
			conn_free(conn);
			return NULL;
		}  
		
		if (lp_status(SNUM(conn)))
			claim_connection(conn,"STATUS.",
					 MAXSTATUS,False);
	} /* IS_IPC */
	
	/* execute any "root preexec = " line */
	if (*lp_rootpreexec(SNUM(conn))) {
		pstring cmd;
		pstrcpy(cmd,lp_rootpreexec(SNUM(conn)));
		standard_sub(conn,cmd);
		DEBUG(5,("cmd=%s\n",cmd));
		ret = smbrun(cmd,NULL,False);
		if (ret != 0 && lp_rootpreexec_close(SNUM(conn))) {
			DEBUG(1,("preexec gave %d - failing connection\n", ret));
			conn_free(conn);
			*ecode = ERRsrverror;
			return NULL;
		}
	}
	
	if (!become_user(conn, conn->vuid)) {
		DEBUG(0,("Can't become connected user!\n"));
		if (!IS_IPC(conn)) {
			yield_connection(conn,
					 lp_servicename(SNUM(conn)),
					 lp_max_connections(SNUM(conn)));
			if (lp_status(SNUM(conn))) {
				yield_connection(conn,"STATUS.",MAXSTATUS);
			}
		}
		conn_free(conn);
		*ecode = ERRbadpw;
		return NULL;
	}
	
	if (dos_ChDir(conn->connectpath) != 0) {
		DEBUG(0,("Can't change directory to %s (%s)\n",
			 conn->connectpath,strerror(errno)));
		unbecome_user();
		if (!IS_IPC(conn)) {
			yield_connection(conn,
					 lp_servicename(SNUM(conn)),
					 lp_max_connections(SNUM(conn)));
			if (lp_status(SNUM(conn))) 
				yield_connection(conn,"STATUS.",MAXSTATUS);
		}
		conn_free(conn);
		*ecode = ERRinvnetname;
		return NULL;
	}
	
	string_set(&conn->origpath,conn->connectpath);
	
#if SOFTLINK_OPTIMISATION
	/* resolve any soft links early */
	{
		pstring s;
		pstrcpy(s,conn->connectpath);
		dos_GetWd(s);
		string_set(&conn->connectpath,s);
		dos_ChDir(conn->connectpath);
	}
#endif
	
	add_session_user(user);
		
	/* execute any "preexec = " line */
	if (*lp_preexec(SNUM(conn))) {
		pstring cmd;
		pstrcpy(cmd,lp_preexec(SNUM(conn)));
		standard_sub(conn,cmd);
		ret = smbrun(cmd,NULL,False);
		if (ret != 0 && lp_preexec_close(SNUM(conn))) {
			DEBUG(1,("preexec gave %d - failing connection\n", ret));
			conn_free(conn);
			*ecode = ERRsrverror;
			return NULL;
		}
	}

	/*
	 * Print out the 'connected as' stuff here as we need
	 * to know the effective uid and gid we will be using.
	 */

	if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
		dbgtext( "%s (%s) ", remote_machine, conn->client_address );
		dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) );
		dbgtext( "as user %s ", user );
		dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
		dbgtext( "(pid %d)\n", (int)getpid() );
	}
	
	/* we've finished with the sensitive stuff */
	unbecome_user();
	
	/* Add veto/hide lists */
	if (!IS_IPC(conn) && !IS_PRINT(conn)) {
		set_namearray( &conn->veto_list, lp_veto_files(SNUM(conn)));
		set_namearray( &conn->hide_list, lp_hide_files(SNUM(conn)));
		set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(SNUM(conn)));
	}
	
	return(conn);
}