Esempio n. 1
0
void fill_share_2(SHARE_INFO_1 *sh1, int snum)
{
	StrnCpy(sh1[0].shi1_netname, "tmp", 13);
	sh1[0].shi1_type = STYPE_DISKTREE;
	sh1[0].shi1_remark = "some weird comment";

	lp_comment(snum);
	lp_pathname(snum);
	StrnCpy(p, lp_servicename(snum), 13);

	type = STYPE_DISKTREE;
	if (lp_print_ok(snum))
		type = STYPE_PRINTQ;
	if (strequal("IPC$", lp_servicename(snum)))
		type = STYPE_IPC;
	lp_comment(snum);
#endif

void fill_share_1(SHARE_INFO_1 *sh1, int snum)
{
	StrnCpy(sh1->shi1_netname, lp_servicename(snum), 13);
	sh1->shi1_remark = lp_comment(snum);
	sh1->shi1_type = STYPE_DISKTREE;
	if (lp_print_ok(snum))
		sh1->shi1_type = STYPE_PRINTQ;
	if (strequal("IPC$", lp_servicename(snum)))
		sh1->shi1_type = STYPE_IPC;
}
Esempio n. 2
0
static NTSTATUS share_sanity_checks(const struct tsocket_address *remote_address,
				    const char *rhost,
				    int snum,
				    fstring dev)
{
	char *raddr;

	raddr = tsocket_address_inet_addr_string(remote_address,
						 talloc_tos());
	if (raddr == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	if (!lp_snum_ok(snum) ||
	    !allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
			  rhost, raddr)) {
		return NT_STATUS_ACCESS_DENIED;
	}

	if (dev[0] == '?' || !dev[0]) {
		if (lp_print_ok(snum)) {
			fstrcpy(dev,"LPT1:");
		} else if (strequal(lp_fstype(snum), "IPC")) {
			fstrcpy(dev, "IPC");
		} else {
			fstrcpy(dev,"A:");
		}
	}

	strupper_m(dev);

	if (lp_print_ok(snum)) {
		if (!strequal(dev, "LPT1:")) {
			return NT_STATUS_BAD_DEVICE_TYPE;
		}
	} else if (strequal(lp_fstype(snum), "IPC")) {
		if (!strequal(dev, "IPC")) {
			return NT_STATUS_BAD_DEVICE_TYPE;
		}
	} else if (!strequal(dev, "A:")) {
		return NT_STATUS_BAD_DEVICE_TYPE;
	}

	/* Behave as a printer if we are supposed to */
	if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
		fstrcpy(dev, "LPT1:");
	}

	return NT_STATUS_OK;
}
Esempio n. 3
0
int print_queue_snum(const char *qname)
{
	int snum = lp_servicenumber(qname);
	if (snum == -1 || !lp_print_ok(snum))
		return -1;
	return snum;
}
Esempio n. 4
0
void reload_printers(void)
{
	int snum;
	int n_services = lp_numservices();
	int pnum = lp_servicenumber(PRINTERS_NAME);
	const char *pname;

	pcap_cache_reload();

	/* remove stale printers */
	for (snum = 0; snum < n_services; snum++) {
		/* avoid removing PRINTERS_NAME or non-autoloaded printers */
		if (snum == pnum || !(lp_snum_ok(snum) && lp_print_ok(snum) &&
		                      lp_autoloaded(snum)))
			continue;

		pname = lp_printername(snum);
		if (!pcap_printername_ok(pname)) {
			DEBUG(3, ("removing stale printer %s\n", pname));

			if (is_printer_published(NULL, snum, NULL))
				nt_printer_publish(NULL, snum, SPOOL_DS_UNPUBLISH);
			del_a_printer(pname);
			lp_killservice(snum);
		}
	}

	load_printers();
}
Esempio n. 5
0
static NTSTATUS share_sanity_checks(int snum, fstring dev) 
{
	
	if (!lp_snum_ok(snum) || 
	    !check_access(smbd_server_fd(), 
			  lp_hostsallow(snum), lp_hostsdeny(snum))) {    
		return NT_STATUS_ACCESS_DENIED;
	}

	if (dev[0] == '?' || !dev[0]) {
		if (lp_print_ok(snum)) {
			fstrcpy(dev,"LPT1:");
		} else if (strequal(lp_fstype(snum), "IPC")) {
			fstrcpy(dev, "IPC");
		} else {
			fstrcpy(dev,"A:");
		}
	}

	strupper_m(dev);

	if (lp_print_ok(snum)) {
		if (!strequal(dev, "LPT1:")) {
			return NT_STATUS_BAD_DEVICE_TYPE;
		}
	} else if (strequal(lp_fstype(snum), "IPC")) {
		if (!strequal(dev, "IPC")) {
			return NT_STATUS_BAD_DEVICE_TYPE;
		}
	} else if (!strequal(dev, "A:")) {
		return NT_STATUS_BAD_DEVICE_TYPE;
	}

	/* Behave as a printer if we are supposed to */
	if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
		fstrcpy(dev, "LPT1:");
	}

	return NT_STATUS_OK;
}
Esempio n. 6
0
/****************************************************************************
 purge stale printers and reload from pre-populated pcap cache
**************************************************************************/
void reload_printers(struct tevent_context *ev,
		     struct messaging_context *msg_ctx)
{
	int n_services;
	int pnum;
	int snum;
	const char *pname;

	n_services = lp_numservices();
	pnum = lp_servicenumber(PRINTERS_NAME);

	DEBUG(10, ("reloading printer services from pcap cache\n"));

	/*
	 * Add default config for printers added to smb.conf file and remove
	 * stale printers
	 */
	for (snum = 0; snum < n_services; snum++) {
		/* avoid removing PRINTERS_NAME */
		if (snum == pnum) {
			continue;
		}

		/* skip no-printer services */
		if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
			continue;
		}

		pname = lp_printername(snum);

		/* check printer, but avoid removing non-autoloaded printers */
		if (lp_autoloaded(snum) && !pcap_printername_ok(pname)) {
			DEBUG(3, ("removing stale printer %s\n", pname));
			lp_killservice(snum);
		}
	}

	/* Make sure deleted printers are gone */
	load_printers(ev, msg_ctx);
}
Esempio n. 7
0
static int key_printers_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
{
	int n_services = lp_numservices();	
	int snum;
	fstring sname;
	int i;
	int num_subkeys = 0;
	char *printers_key;
	char *printername, *printerdatakey;
	NT_PRINTER_INFO_LEVEL *printer = NULL;
	fstring *subkey_names = NULL;
	
	DEBUG(10,("key_printers_fetch_keys: key=>[%s]\n", key ? key : "NULL" ));
	
	printers_key = strip_printers_prefix( key );	
	
	if ( !printers_key ) {
		/* enumerate all printers */
		
		for (snum=0; snum<n_services; snum++) {
			if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
				continue;

			/* don't report the [printers] share */

			if ( strequal( lp_servicename(snum), PRINTERS_NAME ) )
				continue;
				
			fstrcpy( sname, lp_servicename(snum) );
				
			regsubkey_ctr_addkey( subkeys, sname );
		}
		
		num_subkeys = regsubkey_ctr_numkeys( subkeys );
		goto done;
	}

	/* get information for a specific printer */
	
	if (!reg_split_path( printers_key, &printername, &printerdatakey )) {
		return -1;
	}

	/* validate the printer name */

	for (snum=0; snum<n_services; snum++) {
		if ( !lp_snum_ok(snum) || !lp_print_ok(snum) )
			continue;
		if (strequal( lp_servicename(snum), printername ) )
			break;
	}

	if ( snum>=n_services
		|| !W_ERROR_IS_OK( get_a_printer(NULL, &printer, 2, printername) ) ) 
	{
		return -1;
	}

	num_subkeys = get_printer_subkeys( printer->info_2->data, printerdatakey?printerdatakey:"", &subkey_names );
	
	for ( i=0; i<num_subkeys; i++ )
		regsubkey_ctr_addkey( subkeys, subkey_names[i] );
	
	free_a_printer( &printer, 2 );
			
	/* no other subkeys below here */

done:	
	SAFE_FREE( subkey_names );
	
	return num_subkeys;
}
Esempio n. 8
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);
}
Esempio n. 9
0
WERROR check_published_printers(struct messaging_context *msg_ctx)
{
	ADS_STATUS ads_rc;
	ADS_STRUCT *ads = NULL;
	int snum;
	int n_services = lp_numservices();
	TALLOC_CTX *tmp_ctx = NULL;
	struct auth_serversupplied_info *session_info = NULL;
	struct spoolss_PrinterInfo2 *pinfo2;
	NTSTATUS status;
	WERROR result;

	tmp_ctx = talloc_new(NULL);
	if (!tmp_ctx) return WERR_NOMEM;

	ads = ads_init(lp_realm(), lp_workgroup(), NULL);
	if (!ads) {
		DEBUG(3, ("ads_init() failed\n"));
		return WERR_SERVER_UNAVAILABLE;
	}
	setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
	SAFE_FREE(ads->auth.password);
	ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
		NULL, NULL);

	/* ads_connect() will find the DC for us */
	ads_rc = ads_connect(ads);
	if (!ADS_ERR_OK(ads_rc)) {
		DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
		result = WERR_ACCESS_DENIED;
		goto done;
	}

	status = make_session_info_system(tmp_ctx, &session_info);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("check_published_printers: "
			  "Could not create system session_info\n"));
		result = WERR_ACCESS_DENIED;
		goto done;
	}

	for (snum = 0; snum < n_services; snum++) {
		if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
			continue;
		}

		result = winreg_get_printer(tmp_ctx, session_info, msg_ctx,
					    lp_servicename(snum),
					    &pinfo2);
		if (!W_ERROR_IS_OK(result)) {
			continue;
		}

		if (pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
			nt_printer_publish_ads(msg_ctx, ads, pinfo2);
		}

		TALLOC_FREE(pinfo2);
	}

	result = WERR_OK;
done:
	ads_destroy(&ads);
	ads_kdestroy("MEMORY:prtpub_cache");
	talloc_free(tmp_ctx);
	return result;
}
Esempio n. 10
0
/****************************************************************************
 purge stale printers and reload from pre-populated pcap cache
**************************************************************************/
void reload_printers_full(struct tevent_context *ev,
			  struct messaging_context *msg_ctx)
{
	struct auth_serversupplied_info *session_info = NULL;
	int n_services;
	int pnum;
	int snum;
	const char *pname;
	const char *sname;
	NTSTATUS status;

	n_services = lp_numservices();
	pnum = lp_servicenumber(PRINTERS_NAME);

	status = make_session_info_system(talloc_new(NULL), &session_info);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(3, ("Could not create system session_info\n"));
		/* can't remove stale printers before we
		 * are fully initilized */
		return;
	}

	/*
	 * Add default config for printers added to smb.conf file and remove
	 * stale printers
	 */
	for (snum = 0; snum < n_services; snum++) {
		/* avoid removing PRINTERS_NAME */
		if (snum == pnum) {
			continue;
		}

		/* skip no-printer services */
		if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
			continue;
		}

		sname = lp_const_servicename(snum);
		pname = lp_printername(snum);

		/* check printer, but avoid removing non-autoloaded printers */
		if (lp_autoloaded(snum) && !pcap_printername_ok(pname)) {
			struct spoolss_PrinterInfo2 *pinfo2 = NULL;
			if (is_printer_published(session_info, session_info,
						 msg_ctx,
						 NULL,
						 lp_servicename(snum),
						 &pinfo2)) {
				nt_printer_publish(session_info,
						   session_info,
						   msg_ctx,
						   pinfo2,
						   DSPRINT_UNPUBLISH);
				TALLOC_FREE(pinfo2);
			}
			nt_printer_remove(session_info, session_info, msg_ctx,
					  pname);
		} else {
			DEBUG(8, ("Adding default registry entry for printer "
				  "[%s], if it doesn't exist.\n", sname));
			nt_printer_add(session_info, session_info, msg_ctx,
				       sname);
		}
	}

	/* finally, purge old snums */
	reload_printers(ev, msg_ctx);

	TALLOC_FREE(session_info);
}