Пример #1
0
bool cli_send_mailslot(struct messaging_context *msg_ctx,
		       bool unique, const char *mailslot,
		       uint16 priority,
		       char *buf, int len,
		       const char *srcname, int src_type,
		       const char *dstname, int dest_type,
		       const struct sockaddr_storage *dest_ss)
{
	struct packet_struct p;
	struct dgram_packet *dgram = &p.packet.dgram;
	char *ptr, *p2;
	char tmp[4];
	pid_t nmbd_pid;
	char addr[INET6_ADDRSTRLEN];

	if ((nmbd_pid = pidfile_pid("nmbd")) == 0) {
		DEBUG(3, ("No nmbd found\n"));
		return False;
	}

	if (dest_ss->ss_family != AF_INET) {
		DEBUG(3, ("cli_send_mailslot: can't send to IPv6 address.\n"));
		return false;
	}

	memset((char *)&p, '\0', sizeof(p));

	/*
	 * Next, build the DGRAM ...
	 */

	/* DIRECT GROUP or UNIQUE datagram. */
	dgram->header.msg_type = unique ? 0x10 : 0x11;
	dgram->header.flags.node_type = M_NODE;
	dgram->header.flags.first = True;
	dgram->header.flags.more = False;
	dgram->header.dgm_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) +
		((unsigned)sys_getpid()%(unsigned)100);
	/* source ip is filled by nmbd */
	dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
	dgram->header.packet_offset = 0;

	make_nmb_name(&dgram->source_name,srcname,src_type);
	make_nmb_name(&dgram->dest_name,dstname,dest_type);

	ptr = &dgram->data[0];

	/* Setup the smb part. */
	ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
	memcpy(tmp,ptr,4);

	if (smb_size + 17*2 + strlen(mailslot) + 1 + len > MAX_DGRAM_SIZE) {
		DEBUG(0, ("cli_send_mailslot: Cannot write beyond end of packet\n"));
		return False;
	}

	cli_set_message(ptr,17,strlen(mailslot) + 1 + len,True);
	memcpy(ptr,tmp,4);

	SCVAL(ptr,smb_com,SMBtrans);
	SSVAL(ptr,smb_vwv1,len);
	SSVAL(ptr,smb_vwv11,len);
	SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
	SSVAL(ptr,smb_vwv13,3);
	SSVAL(ptr,smb_vwv14,1);
	SSVAL(ptr,smb_vwv15,priority);
	SSVAL(ptr,smb_vwv16,2);
	p2 = smb_buf(ptr);
	fstrcpy(p2,mailslot);
	p2 = skip_string(ptr,MAX_DGRAM_SIZE,p2);
	if (!p2) {
		return False;
	}

	memcpy(p2,buf,len);
	p2 += len;

	dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */

	p.packet_type = DGRAM_PACKET;
	p.ip = ((const struct sockaddr_in *)dest_ss)->sin_addr;
	p.timestamp = time(NULL);

	DEBUG(4,("send_mailslot: Sending to mailslot %s from %s ",
		 mailslot, nmb_namestr(&dgram->source_name)));
	print_sockaddr(addr, sizeof(addr), dest_ss);

	DEBUGADD(4,("to %s IP %s\n", nmb_namestr(&dgram->dest_name), addr));

	return NT_STATUS_IS_OK(messaging_send_buf(msg_ctx,
						  pid_to_procid(nmbd_pid),
						  MSG_SEND_PACKET,
						  (uint8 *)&p, sizeof(p)));
}
Пример #2
0
/****************************************************************************
register a uid/name pair as being valid and that a valid password
has been given. vuid is biased by an offset. This allows us to
tell random client vuid's (normally zero) from valid vuids.
****************************************************************************/
uint16 register_vuid(int uid,int gid, char *unix_name, char *requested_name, BOOL guest)
{
  user_struct *vuser;
  struct passwd *pwfile; /* for getting real name from passwd file */

  /* Ensure no vuid gets registered in share level security. */
  if(lp_security() == SEC_SHARE)
    return UID_FIELD_INVALID;

#if 0
  /*
   * After observing MS-Exchange services writing to a Samba share
   * I belive this code is incorrect. Each service does its own
   * sessionsetup_and_X for the same user, and as each service shuts
   * down, it does a user_logoff_and_X. As we are consolidating multiple
   * sessionsetup_and_X's onto the same vuid here, when the first service
   * shuts down, it invalidates all the open files for the other services.
   * Hence I am removing this code and forcing each sessionsetup_and_X
   * to get a new vuid.
   * Jeremy Allison. ([email protected]).
   */

  int i;
  for(i = 0; i < num_validated_users; i++) {
    vuser = &validated_users[i];
    if ( vuser->uid == uid )
      return (uint16)(i + VUID_OFFSET); /* User already validated */
  }
#endif

  validated_users = (user_struct *)Realloc(validated_users,
			   sizeof(user_struct)*
			   (num_validated_users+1));
  
  if (!validated_users)
    {
      DEBUG(0,("Failed to realloc users struct!\n"));
      num_validated_users = 0;
      return UID_FIELD_INVALID;
    }

  vuser = &validated_users[num_validated_users];
  num_validated_users++;

  vuser->uid = uid;
  vuser->gid = gid;
  vuser->guest = guest;
  fstrcpy(vuser->name,unix_name);
  fstrcpy(vuser->requested_name,requested_name);

  vuser->n_sids = 0;
  vuser->sids   = NULL;

  vuser->n_groups = 0;
  vuser->groups  = NULL;
  vuser->igroups = NULL;
  vuser->attrs    = NULL;

  /* Find all the groups this uid is in and store them. 
     Used by become_user() */
  setup_groups(unix_name,uid,gid,
	       &vuser->n_groups,
	       &vuser->igroups,
	       &vuser->groups,
	       &vuser->attrs);

  DEBUG(3,("uid %d registered to name %s\n",uid,unix_name));

  DEBUG(3, ("Clearing default real name\n"));
  fstrcpy(vuser->real_name, "<Full Name>\0");
  if (lp_unix_realname()) {
    if ((pwfile=getpwnam(vuser->name))!= NULL)
      {
      DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->name,pwfile->pw_gecos));
      fstrcpy(vuser->real_name, pwfile->pw_gecos);
      }
  }

  return (uint16)((num_validated_users - 1) + VUID_OFFSET);
}
Пример #3
0
/****************************************************************************
check if a username/password is OK
****************************************************************************/
BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd)
{
  pstring pass2;
  int level = lp_passwordlevel();
  struct passwd *pass;
  char challenge[8];
  BOOL update_encrypted = lp_update_encrypted();
  struct smb_passwd *smb_pass;
  BOOL challenge_done = False;

  if (password) password[pwlen] = 0;

  if (pwlen == 24)
    challenge_done = last_challenge(challenge);

#if DEBUG_PASSWORD
  if (challenge_done)
    {
      int i;      
      DEBUG(100,("checking user=[%s] pass=[",user));
      for( i = 0; i < 24; i++)
	DEBUG(100,("%0x ", (unsigned char)password[i]));
      DEBUG(100,("]\n"));
    } else {
	    DEBUG(100,("checking user=[%s] pass=[%s]\n",user,password));
    }
#endif

  if (!password)
    return(False);

  if (((!*password) || (!pwlen)) && !lp_null_passwords())
    return(False);

  if (pwd && !user) 
    {
      pass = (struct passwd *) pwd;
      user = pass->pw_name;
    } 
  else 
    pass = Get_Pwnam(user,True);

  DEBUG(4,("SMB Password - pwlen = %d, challenge_done = %d\n", pwlen, challenge_done));

  if ((pwlen == 24) && challenge_done)
  {
    DEBUG(4,("Checking SMB password for user %s (l=24)\n",user));

    if (!pass) 
    {
      DEBUG(3,("Couldn't find user %s\n",user));
      return(False);
    }

    /* non-null username indicates search by username not smb userid */
    smb_pass = get_smbpwd_entry(user, 0);
    if (!smb_pass)
    {
      DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user));
      return(False);
    }

    if(smb_pass->acct_ctrl & ACB_DISABLED)
    {
      DEBUG(3,("password_ok: account for user %s was disabled.\n", user));
          return(False);
    }

      /* Ensure the uid's match */
    if (smb_pass->smb_userid != pass->pw_uid)
    {
      DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n"));
      return(False);
    }

    if (Protocol >= PROTOCOL_NT1)
    {
      /* We have the NT MD4 hash challenge available - see if we can
         use it (ie. does it exist in the smbpasswd file).
       */
      if (smb_pass->smb_nt_passwd != NULL)
      {
        DEBUG(4,("Checking NT MD4 password\n"));
        if (smb_password_check(password, 
                               smb_pass->smb_nt_passwd, 
                               (unsigned char *)challenge))
        {
          update_protected_database(user,True);
          return(True);
        }
        DEBUG(4,("NT MD4 password check failed\n"));
      }
    }

    /* Try against the lanman password */
    if((smb_pass->smb_passwd == NULL) && (smb_pass->acct_ctrl & ACB_PWNOTREQ ))
    {
      /* No password. */
      DEBUG(1,("password_ok: User %s has NO PASSWORD !\n", user));
      update_protected_database(user,True);
      return(True);
    }

    if ((smb_pass->smb_passwd != NULL) && 
        smb_password_check(password, smb_pass->smb_passwd,
                           (unsigned char *)challenge))
    {
      update_protected_database(user,True);
      return(True);
    }

    DEBUG(3,("Error smb_password_check failed\n"));
  }

  DEBUG(4,("Checking password for user %s (l=%d)\n",user,pwlen));

  if (!pass) 
    {
      DEBUG(3,("Couldn't find user %s\n",user));
      return(False);
    }

#ifdef SHADOW_PWD
  {
    struct spwd *spass;

    /* many shadow systems require you to be root to get the password,
       in most cases this should already be the case when this
       function is called, except perhaps for IPC password changing
       requests */

    spass = getspnam(pass->pw_name);
    if (spass && spass->sp_pwdp)
      pass->pw_passwd = spass->sp_pwdp;
  }
#elif defined(IA_UINFO)
  {
      /* Need to get password with SVR4.2's ia_ functions instead of
         get{sp,pw}ent functions. Required by UnixWare 2.x, tested on 
         version 2.1. ([email protected]) */
      uinfo_t uinfo;
      if (ia_openinfo(pass->pw_name, &uinfo) != -1)
        ia_get_logpwd(uinfo, &(pass->pw_passwd));
  }
#endif

#ifdef SecureWare
  {
    struct pr_passwd *pr_pw = getprpwnam(pass->pw_name);
    if (pr_pw && pr_pw->ufld.fd_encrypt)
      pass->pw_passwd = pr_pw->ufld.fd_encrypt;
  }
#endif

#ifdef HPUX_10_TRUSTED
  {
    struct pr_passwd *pr_pw = getprpwnam(pass->pw_name);
    if (pr_pw && pr_pw->ufld.fd_encrypt)
      pass->pw_passwd = pr_pw->ufld.fd_encrypt;
  }
#endif

#ifdef OSF1_ENH_SEC
  {
    struct pr_passwd *mypasswd;
    DEBUG(5,("Checking password for user %s in OSF1_ENH_SEC\n",user));
    mypasswd = getprpwnam (user);
    if ( mypasswd )
      { 
  	pstrcpy(pass->pw_name,mypasswd->ufld.fd_name);
  	pstrcpy(pass->pw_passwd,mypasswd->ufld.fd_encrypt);
      }
    else
      {
	DEBUG(5,("No entry for user %s in protected database !\n",user));
	return(False);
      }
  }
#endif

#ifdef ULTRIX_AUTH
  {
    AUTHORIZATION *ap = getauthuid( pass->pw_uid );
    if (ap)
      {
	pstrcpy( pass->pw_passwd, ap->a_password );
	endauthent();
      }
  }
#endif

  /* extract relevant info */
  fstrcpy(this_user,pass->pw_name);  
  fstrcpy(this_salt,pass->pw_passwd);
#ifdef HPUX
  /* The crypt on HPUX won't work with more than 2 salt characters. */
  this_salt[2] = 0;
#endif /* HPUX */
  fstrcpy(this_crypted,pass->pw_passwd);
 
  if (!*this_crypted) {
    if (!lp_null_passwords()) {
      DEBUG(2,("Disallowing access to %s due to null password\n",this_user));
      return(False);
    }
#ifndef PWDAUTH
    if (!*password) {
      DEBUG(3,("Allowing access to %s with null password\n",this_user));
      return(True);
    }
#endif    
  }

  /* try it as it came to us */
  if (password_check(password))
    {
      update_protected_database(user,True);
      if (pass && update_encrypted)
        update_smbpassword_file(pass,password);
      return(True);
    }

  /* if the password was given to us with mixed case then we don't
     need to proceed as we know it hasn't been case modified by the
     client */
  if (strhasupper(password) && strhaslower(password))
    return(False);

  /* make a copy of it */
  StrnCpy(pass2,password,sizeof(pstring)-1);
  
  /* try all lowercase */
  strlower(password);
  if (password_check(password))
    {
      update_protected_database(user,True);
      if (pass && update_encrypted)
        update_smbpassword_file(pass,password);
      return(True);
    }

  /* give up? */
  if (level < 1)
    {
      update_protected_database(user,False);

      /* restore it */
      pstrcpy(password,pass2);

      return(False);
    }

  /* last chance - all combinations of up to level chars upper! */
  strlower(password);

  if (string_combinations(password,password_check,level))
    {
      update_protected_database(user,True);
      if (pass && update_encrypted)
        update_smbpassword_file(pass,password);
      return(True);
    }

  update_protected_database(user,False);
  
  /* restore it */
  pstrcpy(password,pass2);
  
  return(False);
}
Пример #4
0
static void
execute_command_line (const char *command, bool wait, int *exitstat,
		      int *cmdstat, char *cmdmsg,
		      gfc_charlen_type command_len,
		      gfc_charlen_type cmdmsg_len)
{
  /* Transform the Fortran string to a C string.  */
  char cmd[command_len + 1];
  memcpy (cmd, command, command_len);
  cmd[command_len] = '\0';

  /* Flush all I/O units before executing the command.  */
  flush_all_units();

#if defined(HAVE_FORK)
  if (!wait)
    {
      /* Asynchronous execution.  */
      pid_t pid;

      set_cmdstat (cmdstat, EXEC_NOERROR);

      if ((pid = fork()) < 0)
	set_cmdstat (cmdstat, EXEC_CHILDFAILED);
      else if (pid == 0)
	{
	  /* Child process.  */
	  int res = system (cmd);
	  _exit (WIFEXITED(res) ? WEXITSTATUS(res) : res);
	}
    }
  else
#endif
    {
      /* Synchronous execution.  */
      int res = system (cmd);

      if (res == -1)
	set_cmdstat (cmdstat, EXEC_SYSTEMFAILED);
#ifndef HAVE_FORK
      else if (!wait)
	set_cmdstat (cmdstat, EXEC_SYNCHRONOUS);
#endif
      else
	set_cmdstat (cmdstat, EXEC_NOERROR);

      if (res != -1)
	{
#if defined(WEXITSTATUS) && defined(WIFEXITED)
	  *exitstat = WIFEXITED(res) ? WEXITSTATUS(res) : res;
#else
	  *exitstat = res;
#endif
	}
    }

  /* Now copy back to the Fortran string if needed.  */
  if (cmdstat && *cmdstat > EXEC_NOERROR)
    {
      if (cmdmsg)
	fstrcpy (cmdmsg, cmdmsg_len, cmdmsg_values[*cmdstat],
		strlen (cmdmsg_values[*cmdstat]));
      else
	runtime_error ("Failure in EXECUTE_COMMAND_LINE: %s",
		       cmdmsg_values[*cmdstat]);
    }
}
Пример #5
0
int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute, 
		 void (*fn)(const char *, file_info *, const char *, void *), void *state)
{
	char *p;
	int received = 0;
	BOOL first = True;
	char status[21];
	int num_asked = (cli->max_xmit - 100)/DIR_STRUCT_SIZE;
	int num_received = 0;
	int i;
	char *dirlist = NULL;
	pstring mask;
	
	ZERO_ARRAY(status);

	pstrcpy(mask,Mask);
  
	while (1) {
		memset(cli->outbuf,'\0',smb_size);
		memset(cli->inbuf,'\0',smb_size);

		set_message(cli->outbuf,2,0,True);

		SCVAL(cli->outbuf,smb_com,SMBsearch);

		SSVAL(cli->outbuf,smb_tid,cli->cnum);
		cli_setup_packet(cli);

		SSVAL(cli->outbuf,smb_vwv0,num_asked);
		SSVAL(cli->outbuf,smb_vwv1,attribute);
  
		p = smb_buf(cli->outbuf);
		*p++ = 4;
      
		p += clistr_push(cli, p, first?mask:"", -1, STR_TERMINATE);
		*p++ = 5;
		if (first) {
			SSVAL(p,0,0);
			p += 2;
		} else {
			SSVAL(p,0,21);
			p += 2;
			memcpy(p,status,21);
			p += 21;
		}

		cli_setup_bcc(cli, p);
		cli_send_smb(cli);
		if (!cli_receive_smb(cli)) break;

		received = SVAL(cli->inbuf,smb_vwv0);
		if (received <= 0) break;

		first = False;

		dirlist = (char *)SMB_REALLOC(
			dirlist,(num_received + received)*DIR_STRUCT_SIZE);
		if (!dirlist) {
			DEBUG(0,("cli_list_old: failed to expand dirlist"));
			return 0;
		}

		p = smb_buf(cli->inbuf) + 3;

		memcpy(dirlist+num_received*DIR_STRUCT_SIZE,
		       p,received*DIR_STRUCT_SIZE);
		
		memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21);
		
		num_received += received;
		
		if (cli_is_error(cli)) break;
	}

	if (!first) {
		memset(cli->outbuf,'\0',smb_size);
		memset(cli->inbuf,'\0',smb_size);

		set_message(cli->outbuf,2,0,True);
		SCVAL(cli->outbuf,smb_com,SMBfclose);
		SSVAL(cli->outbuf,smb_tid,cli->cnum);
		cli_setup_packet(cli);

		SSVAL(cli->outbuf, smb_vwv0, 0); /* find count? */
		SSVAL(cli->outbuf, smb_vwv1, attribute);

		p = smb_buf(cli->outbuf);
		*p++ = 4;
		fstrcpy(p, "");
		p += strlen(p) + 1;
		*p++ = 5;
		SSVAL(p, 0, 21);
		p += 2;
		memcpy(p,status,21);
		p += 21;
		
		cli_setup_bcc(cli, p);
		cli_send_smb(cli);
		if (!cli_receive_smb(cli)) {
			DEBUG(0,("Error closing search: %s\n",cli_errstr(cli)));
		}
	}

	for (p=dirlist,i=0;i<num_received;i++) {
		file_info finfo;
		p += interpret_short_filename(cli, p,&finfo);
		fn("\\", &finfo, Mask, state);
	}

	SAFE_FREE(dirlist);
	return(num_received);
}
Пример #6
0
static char *validate_group(char *group, DATA_BLOB password,int snum)
{
#ifdef HAVE_NETGROUP
	{
		char *host, *user, *domain;
		setnetgrent(group);
		while (getnetgrent(&host, &user, &domain)) {
			if (user) {
				if (user_ok(user, snum) && 
				    password_ok(user,password)) {
					endnetgrent();
					return(user);
				}
			}
		}
		endnetgrent();
	}
#endif
  
#ifdef HAVE_GETGRENT
	{
		struct group *gptr;
		setgrent();
		while ((gptr = (struct group *)getgrent())) {
			if (strequal(gptr->gr_name,group))
				break;
		}

		/*
		 * As user_ok can recurse doing a getgrent(), we must
		 * copy the member list into a pstring on the stack before
		 * use. Bug pointed out by [email protected].
		 */

		if (gptr) {
			pstring member_list;
			char *member;
			size_t copied_len = 0;
			int i;

			*member_list = '\0';
			member = member_list;

			for(i = 0; gptr->gr_mem && gptr->gr_mem[i]; i++) {
				size_t member_len = strlen(gptr->gr_mem[i])+1;
				if(copied_len+member_len < sizeof(pstring)) { 

					DEBUG(10,("validate_group: = gr_mem = "
						  "%s\n", gptr->gr_mem[i]));

					safe_strcpy(member, gptr->gr_mem[i],
						    sizeof(pstring) -
						    copied_len - 1);
					copied_len += member_len;
					member += copied_len;
				} else {
					*member = '\0';
				}
			}

			endgrent();

			member = member_list;
			while (*member) {
				static fstring name;
				fstrcpy(name,member);
				if (user_ok(name,snum) &&
				    password_ok(name,password)) {
					endgrent();
					return(&name[0]);
				}

				DEBUG(10,("validate_group = member = %s\n",
					  member));

				member += strlen(member) + 1;
			}
		} else {
			endgrent();
			return NULL;
		}
	}
#endif
	return(NULL);
}
Пример #7
0
enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) 
{
	NTSTATUS result;
	fstring name_domain, name_user;
	unsigned char trust_passwd[16];
	time_t last_change_time;
	uint32 sec_channel_type;
        NET_USER_INFO_3 info3;
        struct cli_state *cli = NULL;
	uchar chal[8];
	TALLOC_CTX *mem_ctx = NULL;
	DATA_BLOB lm_resp;
	DATA_BLOB nt_resp;
	DOM_CRED ret_creds;
	int attempts = 0;
	unsigned char local_lm_response[24];
	unsigned char local_nt_response[24];
	struct winbindd_domain *contact_domain;
	BOOL retry;

	/* Ensure null termination */
	state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0';

	/* Ensure null termination */
	state->request.data.auth.pass[sizeof(state->request.data.auth.pass)-1]='\0';

	DEBUG(3, ("[%5lu]: pam auth %s\n", (unsigned long)state->pid,
		  state->request.data.auth.user));

	if (!(mem_ctx = talloc_init("winbind pam auth for %s", state->request.data.auth.user))) {
		DEBUG(0, ("winbindd_pam_auth: could not talloc_init()!\n"));
		result = NT_STATUS_NO_MEMORY;
		goto done;
	}

	/* Parse domain and username */
	
	parse_domain_user(state->request.data.auth.user, name_domain, name_user);

	/* do password magic */
	
	generate_random_buffer(chal, 8);
	SMBencrypt(state->request.data.auth.pass, chal, local_lm_response);
		
	SMBNTencrypt(state->request.data.auth.pass, chal, local_nt_response);

	lm_resp = data_blob_talloc(mem_ctx, local_lm_response, sizeof(local_lm_response));
	nt_resp = data_blob_talloc(mem_ctx, local_nt_response, sizeof(local_nt_response));
	
	/* what domain should we contact? */
	
	if ( IS_DC ) {
		if (!(contact_domain = find_domain_from_name(name_domain))) {
			DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", 
				  state->request.data.auth.user, name_domain, name_user, name_domain)); 
			result = NT_STATUS_NO_SUCH_USER;
			goto done;
		}
		
	} else {
		if (is_myname(name_domain)) {
			DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain));
			result =  NT_STATUS_NO_SUCH_USER;
			goto done;
		}

		if (!(contact_domain = find_our_domain())) {
			DEBUG(1, ("Authentication for [%s] -> [%s]\\[%s] in our domain failed - we can't find our domain!\n", 
				  state->request.data.auth.user, name_domain, name_user)); 
			result = NT_STATUS_NO_SUCH_USER;
			goto done;
		}
	}

	if ( !get_trust_pw(contact_domain->name, trust_passwd, &last_change_time, &sec_channel_type) ) {
		result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
		goto done;
	}

	/* check authentication loop */

	do {
		ZERO_STRUCT(info3);
		ZERO_STRUCT(ret_creds);
		retry = False;
	
		/* Don't shut this down - it belongs to the connection cache code */
		result = cm_get_netlogon_cli(contact_domain, trust_passwd, 
					     sec_channel_type, False, &cli);

		if (!NT_STATUS_IS_OK(result)) {
			DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
			goto done;
		}

		result = cli_netlogon_sam_network_logon(cli, mem_ctx,
							&ret_creds,
							name_user, name_domain, 
							global_myname(), chal, 
							lm_resp, nt_resp,
							&info3);
		attempts += 1;
		
		/* We have to try a second time as cm_get_netlogon_cli
		   might not yet have noticed that the DC has killed
		   our connection. */

		if ( cli->fd == -1 ) {
			retry = True;
			continue;
		} 
		
		/* if we get access denied, a possible cuase was that we had and open
		   connection to the DC, but someone changed our machine account password
		   out from underneath us using 'net rpc changetrustpw' */
		   
		if ( NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) ) {
			DEBUG(3,("winbindd_pam_auth: sam_logon returned ACCESS_DENIED.  Maybe the trust account "
				"password was changed and we didn't know it.  Killing connections to domain %s\n",
				name_domain));
			winbindd_cm_flush();
			retry = True;
			cli = NULL;
		} 
		
	} while ( (attempts < 2) && retry );

        if (cli != NULL) {
		/* We might have come out of the loop above with cli == NULL,
		   so don't dereference that. */
		clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds);
	}
	
	if (NT_STATUS_IS_OK(result)) {
		netsamlogon_cache_store( cli->mem_ctx, &info3 );
		wcache_invalidate_samlogon(find_domain_from_name(name_domain), &info3);

		/* Check if the user is in the right group */

		if (!NT_STATUS_IS_OK(result = check_info3_in_group(mem_ctx, &info3, state->request.data.auth.required_membership_sid))) {
			DEBUG(3, ("User %s is not in the required group (%s), so plaintext authentication is rejected\n",
				  state->request.data.auth.user, 
				  state->request.data.auth.required_membership_sid));
		}
	}

done:
	/* give us a more useful (more correct?) error code */
	if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
		result = NT_STATUS_NO_LOGON_SERVERS;
	}
	
	state->response.data.auth.nt_status = NT_STATUS_V(result);
	fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));

	/* we might have given a more useful error above */
	if (!*state->response.data.auth.error_string) 
		fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result));
	state->response.data.auth.pam_error = nt_status_to_pam(result);

	DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Plain-text authentication for user %s returned %s (PAM: %d)\n", 
	      state->request.data.auth.user, 
	      state->response.data.auth.nt_status_string,
	      state->response.data.auth.pam_error));	      

	if ( NT_STATUS_IS_OK(result) &&
	     (state->request.flags & WBFLAG_PAM_AFS_TOKEN) ) {

		char *afsname = strdup(lp_afs_username_map());
		char *cell;

		if (afsname == NULL) goto no_token;

		afsname = realloc_string_sub(afsname, "%D", name_domain);
		afsname = realloc_string_sub(afsname, "%u", name_user);
		afsname = realloc_string_sub(afsname, "%U", name_user);

		if (afsname == NULL) goto no_token;

		strlower_m(afsname);

		cell = strchr(afsname, '@');

		if (cell == NULL) goto no_token;

		*cell = '\0';
		cell += 1;

		/* Append an AFS token string */
		state->response.extra_data =
			afs_createtoken_str(afsname, cell);

		if (state->response.extra_data != NULL)
			state->response.length +=
				strlen(state->response.extra_data)+1;

	no_token:
		SAFE_FREE(afsname);
	}
		
	if (mem_ctx) 
		talloc_destroy(mem_ctx);
	
	return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
}
Пример #8
0
static int iprint_queue_get(const char *sharename,
			    enum printing_types printing_type,
			    char *lpq_command,
			    print_queue_struct **q, 
			    print_status_struct *status)
{
	fstring		printername;
	http_t		*http = NULL;		/* HTTP connection to server */
	ipp_t		*request = NULL,	/* IPP Request */
			*response = NULL;	/* IPP Response */
	ipp_attribute_t	*attr = NULL;		/* Current attribute */
	cups_lang_t	*language = NULL;	/* Default language */
	char		uri[HTTP_MAX_URI]; /* printer-uri attribute */
	char		serviceUri[HTTP_MAX_URI]; /* service-uri attribute */
	char		httpPath[HTTP_MAX_URI];	/* path portion of the uri */
	int		jobUseUnixTime = 0;	/* Whether job times should
                                                 * be assumed to be Unix time */
	int		qcount = 0,		/* Number of active queue entries */
			qalloc = 0;		/* Number of queue entries allocated */
	print_queue_struct *queue = NULL,	/* Queue entries */
			*temp;		/* Temporary pointer for queue */
	const char	*user_name,	/* job-originating-user-name attribute */
			*job_name;	/* job-name attribute */
	int		job_id;		/* job-id attribute */
	int		job_k_octets;	/* job-k-octets attribute */
	time_t		job_time;	/* time-at-creation attribute */
	time_t		printer_up_time = 0;	/* printer's uptime */
	ipp_jstate_t	job_status;	/* job-status attribute */
	int		job_priority;	/* job-priority attribute */
	static const char *jattrs[] =	/* Requested job attributes */
			{
			  "job-id",
			  "job-k-octets",
			  "job-name",
			  "job-originating-user-name",
			  "job-priority",
			  "job-state",
			  "time-at-creation",
			};
	static const char *pattrs[] =	/* Requested printer attributes */
			{
			  "printer-state",
			  "printer-state-message",
			  "printer-current-time",
			  "printer-up-time"
			};

	*q = NULL;

	/* HACK ALERT!!!  The porblem with support the 'printer name' 
	   option is that we key the tdb off the sharename.  So we will 
	   overload the lpq_command string to pass in the printername 
	   (which is basically what we do for non-cups printers ... using 
	   the lpq_command to get the queue listing). */

	fstrcpy( printername, lpq_command );

	DEBUG(5,("iprint_queue_get(%s, %p, %p)\n", printername, q, status));

       /*
	* Make sure we don't ask for passwords...
	*/

	cupsSetPasswordCB(iprint_passwd_cb);

       /*
	* Try to connect to the server...
	*/

	if ((http = httpConnect(iprint_server(), ippPort())) == NULL) {
		DEBUG(0,("Unable to connect to iPrint server %s - %s\n", 
			 iprint_server(), strerror(errno)));
		goto out;
	}

       /*
	* Generate the printer URI and the service URI that goes with it...
	*/

	slprintf(uri, sizeof(uri) - 1, "ipp://%s/ipp/%s", iprint_server(), printername);
	slprintf(serviceUri, sizeof(serviceUri) - 1, "ipp://%s/ipp/", iprint_server());

       /*
	* For Linux iPrint servers from OES SP1 on, the iPrint server
	* uses Unix time for job start times unless it detects the iPrint
	* client in an http User-Agent header.  (This was done to accomodate
	* CUPS broken behavior.  According to RFC 2911, section 4.3.14, job
	* start times are supposed to be relative to how long the printer has
	* been up.)  Since libcups doesn't allow us to set that header before
	* the request is sent, this ugly hack allows us to detect the server
	* version and decide how to interpret the job time.
	*/
	if (iprint_get_server_version(http, serviceUri) >=
	    NOVELL_SERVER_VERSION_OES_SP1)
		jobUseUnixTime = 1;

	request = ippNew();

	ippSetOperation(request, IPP_GET_PRINTER_ATTRIBUTES);
	ippSetRequestId(request, 2);

	language = cupsLangDefault();

	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
	             "attributes-charset", NULL, "utf-8");

	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
	             "attributes-natural-language", NULL, language->language);

	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
	             "printer-uri", NULL, uri);

	ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
	              "requested-attributes",
	              (sizeof(pattrs) / sizeof(pattrs[0])),
	              NULL, pattrs);

       /*
	* Do the request and get back a response...
	*/

	slprintf(httpPath, sizeof(httpPath) - 1, "/ipp/%s", printername);

	if ((response = cupsDoRequest(http, request, httpPath)) == NULL) {
		DEBUG(0,("Unable to get printer status for %s - %s\n", printername,
			 ippErrorString(cupsLastError())));
		*q = queue;
		goto out;
	}

	if (ippGetStatusCode(response) >= IPP_OK_CONFLICT) {
		DEBUG(0,("Unable to get printer status for %s - %s\n", printername,
			 ippErrorString(ippGetStatusCode(response))));
		*q = queue;
		goto out;
	}

       /*
	* Get the current printer status and convert it to the SAMBA values.
	*/

	if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL) {
		if (ippGetInteger(attr, 0) == IPP_PRINTER_STOPPED)
			status->status = LPSTAT_STOPPED;
		else
			status->status = LPSTAT_OK;
	}

	if ((attr = ippFindAttribute(response, "printer-state-message",
	                             IPP_TAG_TEXT)) != NULL)
		fstrcpy(status->message, ippGetString(attr, 0, NULL));

	if ((attr = ippFindAttribute(response, "printer-up-time",
	                             IPP_TAG_INTEGER)) != NULL)
		printer_up_time = ippGetInteger(attr, 0);

	ippDelete(response);
	response = NULL;

       /*
	* Build an IPP_GET_JOBS request, which requires the following
	* attributes:
	*
	*    attributes-charset
	*    attributes-natural-language
	*    requested-attributes
	*    printer-uri
	*/

	request = ippNew();

	ippSetOperation(request, IPP_GET_JOBS);
	ippSetRequestId(request, 3);

	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
	             "attributes-charset", NULL, "utf-8");

	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
	             "attributes-natural-language", NULL, language->language);

	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
	             "printer-uri", NULL, uri);

	ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
	              "requested-attributes",
	              (sizeof(jattrs) / sizeof(jattrs[0])),
	              NULL, jattrs);

       /*
	* Do the request and get back a response...
	*/

	slprintf(httpPath, sizeof(httpPath) - 1, "/ipp/%s", printername);

	if ((response = cupsDoRequest(http, request, httpPath)) == NULL) {
		DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
			 ippErrorString(cupsLastError())));
		goto out;
	}

	if (ippGetStatusCode(response) >= IPP_OK_CONFLICT) {
		DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
			 ippErrorString(ippGetStatusCode(response))));
		goto out;
	}

       /*
	* Process the jobs...
	*/

	qcount = 0;
	qalloc = 0;
	queue  = NULL;

	for (attr = ippFirstAttribute(response); attr != NULL; attr = ippNextAttribute(response)) {
	       /*
		* Skip leading attributes until we hit a job...
		*/

		while (attr != NULL && ippGetGroupTag(attr) != IPP_TAG_JOB)
			attr = ippNextAttribute(response);

		if (attr == NULL)
			break;

	       /*
		* Allocate memory as needed...
		*/
		if (qcount >= qalloc) {
			qalloc += 16;

			queue = SMB_REALLOC_ARRAY(queue, print_queue_struct, qalloc);

			if (queue == NULL) {
				DEBUG(0,("iprint_queue_get: Not enough memory!"));
				qcount = 0;
				goto out;
			}
		}

		temp = queue + qcount;
		memset(temp, 0, sizeof(print_queue_struct));

	       /*
		* Pull the needed attributes from this job...
		*/

		job_id       = 0;
		job_priority = 50;
		job_status   = IPP_JOB_PENDING;
		job_time     = 0;
		job_k_octets = 0;
		user_name    = NULL;
		job_name     = NULL;

		while (attr != NULL && ippGetGroupTag(attr) == IPP_TAG_JOB) {
			if (ippGetName(attr) == NULL) {
				attr = ippNextAttribute(response);
				break;
			}

			if (strcmp(ippGetName(attr), "job-id") == 0 &&
			    ippGetValueTag(attr) == IPP_TAG_INTEGER)
				job_id = ippGetInteger(attr, 0);

			if (strcmp(ippGetName(attr), "job-k-octets") == 0 &&
			    ippGetValueTag(attr) == IPP_TAG_INTEGER)
				job_k_octets = ippGetInteger(attr, 0);

			if (strcmp(ippGetName(attr), "job-priority") == 0 &&
			    ippGetValueTag(attr) == IPP_TAG_INTEGER)
				job_priority = ippGetInteger(attr, 0);

			if (strcmp(ippGetName(attr), "job-state") == 0 &&
			    ippGetValueTag(attr) == IPP_TAG_ENUM)
				job_status = (ipp_jstate_t)ippGetInteger(attr, 0);

			if (strcmp(ippGetName(attr), "time-at-creation") == 0 &&
			    ippGetValueTag(attr) == IPP_TAG_INTEGER)
			{
			       /*
				* If jobs times are in Unix time, the accuracy of the job
				* start time depends upon the iPrint server's time being
				* set correctly.  Otherwise, the accuracy depends upon
				* the Samba server's time being set correctly
				*/

				if (jobUseUnixTime)
					job_time = ippGetInteger(attr, 0);
				else
					job_time = time(NULL) - printer_up_time + ippGetInteger(attr, 0);
			}

			if (strcmp(ippGetName(attr), "job-name") == 0 &&
			    (ippGetValueTag(attr) == IPP_TAG_NAMELANG ||
			     ippGetValueTag(attr) == IPP_TAG_NAME))
				job_name = ippGetString(attr, 0, NULL);

			if (strcmp(ippGetName(attr), "job-originating-user-name") == 0 &&
			    (ippGetValueTag(attr) == IPP_TAG_NAMELANG ||
			     ippGetValueTag(attr) == IPP_TAG_NAME))
				user_name = ippGetString(attr, 0, NULL);

			attr = ippNextAttribute(response);
		}

	       /*
		* See if we have everything needed...
		*/

		if (user_name == NULL || job_name == NULL || job_id == 0) {
			if (attr == NULL)
				break;
			else
				continue;
		}

		temp->sysjob   = job_id;
		temp->size     = job_k_octets * 1024;
		temp->status   = job_status == IPP_JOB_PENDING ? LPQ_QUEUED :
		                 job_status == IPP_JOB_STOPPED ? LPQ_PAUSED :
                                 job_status == IPP_JOB_HELD ? LPQ_PAUSED :
                                 LPQ_PRINTING;
		temp->priority = job_priority;
		temp->time     = job_time;
		strncpy(temp->fs_user, user_name, sizeof(temp->fs_user) - 1);
		strncpy(temp->fs_file, job_name, sizeof(temp->fs_file) - 1);

		qcount ++;

		if (attr == NULL)
			break;
	}

       /*
	* Return the job queue...
	*/

	*q = queue;

 out:
	if (response)
		ippDelete(response);

	if (language)
		cupsLangFree(language);

	if (http)
		httpClose(http);

	return qcount;
}
Пример #9
0
LONG SmartReadArgs(struct WBStartup * wb_startup, struct SmartArgs * args)
{
   LONG error;

   args->sa_Flags = 0;

   D(bug("UtilityBase = 0x%lx\n", (ULONG) UtilityBase));
   D(bug("IconBase    = 0x%lx\n", (ULONG) IconBase));
   D(bug("WBStartup   = 0x%lx\n", (ULONG) wb_startup));

   if (wb_startup != NULL)
   {
      struct WBArg *wbarg = wb_startup->sm_ArgList;
      LONG arg_counter = 0;

      D(bug("  numArgs   = %ld\n", wb_startup->sm_NumArgs));
      while (arg_counter < wb_startup->sm_NumArgs)
      {
         D(bug("  name[%ld] = \"%s\"\n", arg_counter, wbarg->wa_Name));
         wbarg += 1;
         arg_counter += 1;
      }
   }

   if (wb_startup != NULL)
   {
      if (!(args->sa_RDArgs = AllocDosObject(DOS_RDARGS, NULL)))
      {
         return (ERROR_NO_FREE_STORE);
      }
      else
      {
         args->sa_Flags |= SAF_ALLOCRDARGS;

         if (!args->sa_Buffer)
         {
            args->sa_BufferSize = MAX(SA_MINIMUM_BUFFER_SIZE, args->sa_BufferSize);
            args->sa_Buffer = AllocMem(args->sa_BufferSize, MEMF_ANY);
            args->sa_Flags |= SAF_ALLOCBUFFER;
         }

         if (!args->sa_Buffer)
            return (ERROR_NO_FREE_STORE);
         else
         {
            struct DiskObject *dobj;

            args->sa_ActualPtr = args->sa_Buffer;
            args->sa_EndPtr = args->sa_Buffer + args->sa_BufferSize - 1;

            if (!(dobj = smart_get_icon(args, wb_startup)))
            {
               return (ERROR_OBJECT_NOT_FOUND);
            }
            else
            {
               struct WBArg *wbarg = args->sa_WBArg;
               ULONG num = args->sa_NumArgs;

               STRPTR *tooltypes = (STRPTR *) dobj->do_ToolTypes;
               STRPTR name;
               STRPTR temp;
               STRPTR ptr;

               if (num > 1 && args->sa_FileParameter >= 0 && (temp = AllocMem(TEMPSIZE, MEMF_ANY)))
               {
                  ULONG modes = 0;

                  get_arg_name(args, temp, TEMPSIZE, &modes);
                  fstrcpy(args, temp);
                  fstrcpy(args, " ");

                  /* no "/M" specifier in the ReadArgs() template, thus use only the first file */
                  if (modes != MODE_MULTI)
                     num = 2;

                  while (num > 1)
                  {
                     get_wbarg_name(wbarg, temp, TEMPSIZE);
                     fstrcpy(args, "\"");
                     fstrcpy(args, temp);
                     fstrcpy(args, "\" ");
                     num--;
                     wbarg++;
                  }

                  FreeMem(temp, TEMPSIZE);
               }

               D(bug("tooltypes=%lx\n", (ULONG) tooltypes));
               if (tooltypes)
               {
                  while (*tooltypes)
                  {
                     ptr = *tooltypes;
                     name = ptr;

                     /* check if this tooltype enabled and part of the
                      * template */
                     if ((*ptr != '(')
                         && is_in_template(name, args->sa_Template))
                     {
                        while (*ptr != '=' && *ptr != EOS)
                           ptr++;

                        if (*ptr == '=')
                        {
                           *ptr = EOS;

                           if (!Stricmp(name, "WINDOW"))
                           {
                              STRPTR win;
                              if ((win = AllocVec(strlen(ptr + 1) + 1, MEMF_ANY)))
                              {
                                 strcpy(win, ptr + 1);
                                 args->sa_Window = win;
                                 args->sa_Flags |= SAF_ALLOCWINDOW;
                              }

                           }
                           else
                           {
                              fstrcpy(args, name);

                              /* enclose the argument in "" */
                              if (*(ptr + 1) == '"')
                              {
                                 fstrcpy(args, "=");
                                 fstrcpy(args, ptr + 1);
                              }
                              else
                              {
                                 fstrcpy(args, "=\"");
                                 fstrcpy(args, ptr + 1);
                                 fstrcpy(args, "\"");
                              }

                              *ptr = '=';
                           }
                        }
                        else
                           fstrcpy(args, name);

                        fstrcpy(args, " ");
                     }
                     tooltypes++;
                  }             /* while (*tooltypes) */
               }                /* if (tooltypes) */
               fstrcpy(args, "\n");

               D(bug("final wb command line : \"%s\"\n", args->sa_Buffer));
            }
         }
      }

      args->sa_RDArgs->RDA_Source.CS_Buffer = args->sa_Buffer;
      args->sa_RDArgs->RDA_Source.CS_Length = strlen(args->sa_Buffer);

      args->sa_Flags |= SAF_WORKBENCH;
   }

   args->sa_FreeArgs = ReadArgs(args->sa_Template, args->sa_Parameter, args->sa_RDArgs);

   if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
   {
      SetIoErr(ERROR_BREAK);
   }

   if ((error = IoErr()) == 0 && (wb_startup != NULL))
   {
      if (args->sa_Window)
      {
         args->sa_WindowFH = Open(args->sa_Window, MODE_NEWFILE);
         if (args->sa_WindowFH)
         {
            args->sa_OldOutput = SelectOutput(args->sa_WindowFH);
            args->sa_OldInput = SelectInput(args->sa_WindowFH);
         }
      }
   }

   return (error);
}
Пример #10
0
static NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn,
					connection_struct *conn,
					int snum, struct user_struct *vuser,
					const char *pdev)
{
	struct smbd_server_connection *sconn = xconn->client->sconn;
	struct smb_filename *smb_fname_cpath = NULL;
	fstring dev;
	int ret;
	bool on_err_call_dis_hook = false;
	uid_t effuid;
	gid_t effgid;
	NTSTATUS status;

	fstrcpy(dev, pdev);

	status = share_sanity_checks(sconn->remote_address,
				       sconn->remote_hostname,
				       snum,
				       dev);
	if (NT_STATUS_IS_ERR(status)) {
		goto err_root_exit;
	}

	conn->params->service = snum;

	status = create_connection_session_info(sconn,
		conn, snum, vuser->session_info,
		&conn->session_info);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("create_connection_session_info failed: %s\n",
			  nt_errstr(status)));
		goto err_root_exit;
	}

	if (lp_guest_only(snum)) {
		conn->force_user = true;
	}

	conn->num_files_open = 0;
	conn->lastused = conn->lastused_count = time(NULL);
	conn->printer = (strncmp(dev,"LPT",3) == 0);
	conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
		      ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );

	/* Case options for the share. */
	if (lp_case_sensitive(snum) == Auto) {
		/* We will be setting this per packet. Set to be case
		 * insensitive for now. */
		conn->case_sensitive = False;
	} else {
		conn->case_sensitive = (bool)lp_case_sensitive(snum);
	}

	conn->case_preserve = lp_preserve_case(snum);
	conn->short_case_preserve = lp_short_preserve_case(snum);

	conn->encrypt_level = lp_smb_encrypt(snum);

	conn->veto_list = NULL;
	conn->hide_list = NULL;
	conn->veto_oplock_list = NULL;
	conn->aio_write_behind_list = NULL;

	conn->read_only = lp_read_only(SNUM(conn));

	status = set_conn_force_user_group(conn, snum);
	if (!NT_STATUS_IS_OK(status)) {
		goto err_root_exit;
	}

	conn->vuid = vuser->vuid;

	{
		char *s = talloc_sub_advanced(talloc_tos(),
					lp_servicename(talloc_tos(), SNUM(conn)),
					conn->session_info->unix_info->unix_name,
					conn->connectpath,
					conn->session_info->unix_token->gid,
					conn->session_info->unix_info->sanitized_username,
					conn->session_info->info->domain_name,
					lp_path(talloc_tos(), snum));
		if (!s) {
			status = NT_STATUS_NO_MEMORY;
			goto err_root_exit;
		}

		if (!set_conn_connectpath(conn,s)) {
			TALLOC_FREE(s);
			status = NT_STATUS_NO_MEMORY;
			goto err_root_exit;
		}
		DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
			 lp_servicename(talloc_tos(), snum)));
		TALLOC_FREE(s);
	}

	/*
	 * Set up the share security descriptor.
	 * NOTE - we use the *INCOMING USER* session_info
	 * here, as does (indirectly) change_to_user(),
	 * which can be called on any incoming packet.
	 * This way we set up the share access based
	 * on the authenticated user, not the forced
	 * user. See bug:
	 *
	 * https://bugzilla.samba.org/show_bug.cgi?id=9878
	 */

	status = check_user_share_access(conn,
					vuser->session_info,
					&conn->share_access,
					&conn->read_only);
	if (!NT_STATUS_IS_OK(status)) {
		goto err_root_exit;
	}

	/* Initialise VFS function pointers */

	if (!smbd_vfs_init(conn)) {
		DEBUG(0, ("vfs_init failed for service %s\n",
			  lp_servicename(talloc_tos(), snum)));
		status = NT_STATUS_BAD_NETWORK_NAME;
		goto err_root_exit;
	}

/* ROOT Activities: */
	/* explicitly check widelinks here so that we can correctly warn
	 * in the logs. */
	widelinks_warning(snum);

	/*
	 * Enforce the max connections parameter.
	 */

	if ((lp_max_connections(snum) > 0)
	    && (count_current_connections(lp_servicename(talloc_tos(), SNUM(conn)), True) >=
		lp_max_connections(snum))) {

		DEBUG(1, ("Max connections (%d) exceeded for %s\n",
			  lp_max_connections(snum),
			  lp_servicename(talloc_tos(), snum)));
		status = NT_STATUS_INSUFFICIENT_RESOURCES;
		goto err_root_exit;
	}

	/* Invoke VFS make connection hook - this must be the first
	   filesystem operation that we do. */

	if (SMB_VFS_CONNECT(conn, lp_servicename(talloc_tos(), snum),
			    conn->session_info->unix_info->unix_name) < 0) {
		DBG_WARNING("SMB_VFS_CONNECT for service '%s' at '%s' failed: %s\n",
			    lp_servicename(talloc_tos(), snum), conn->connectpath,
			    strerror(errno));
		status = NT_STATUS_UNSUCCESSFUL;
		goto err_root_exit;
	}

	/* Any error exit after here needs to call the disconnect hook. */
	on_err_call_dis_hook = true;

	if ((!conn->printer) && (!conn->ipc) &&
	    lp_change_notify()) {
		if (sconn->notify_ctx == NULL) {
			sconn->notify_ctx = notify_init(
				sconn, sconn->msg_ctx, sconn->ev_ctx);
			status = messaging_register(
				sconn->msg_ctx, sconn,
				MSG_SMB_NOTIFY_CANCEL_DELETED,
				smbd_notify_cancel_deleted);
		}
		if (sconn->sys_notify_ctx == NULL) {
			sconn->sys_notify_ctx = sys_notify_context_create(
				sconn, sconn->ev_ctx);
		}
	}

	if (lp_kernel_oplocks(snum)) {
		init_kernel_oplocks(conn->sconn);
	}

	/*
	 * Fix compatibility issue pointed out by Volker.
	 * We pass the conn->connectpath to the preexec
	 * scripts as a parameter, so attempt to canonicalize
	 * it here before calling the preexec scripts.
	 * We ignore errors here, as it is possible that
	 * the conn->connectpath doesn't exist yet and
	 * the preexec scripts will create them.
	 */

	(void)canonicalize_connect_path(conn);

	/* Preexecs are done here as they might make the dir we are to ChDir
	 * to below */
	/* execute any "root preexec = " line */
	if (*lp_root_preexec(talloc_tos(), snum)) {
		char *cmd = talloc_sub_advanced(talloc_tos(),
					lp_servicename(talloc_tos(), SNUM(conn)),
					conn->session_info->unix_info->unix_name,
					conn->connectpath,
					conn->session_info->unix_token->gid,
					conn->session_info->unix_info->sanitized_username,
					conn->session_info->info->domain_name,
					lp_root_preexec(talloc_tos(), snum));
		DEBUG(5,("cmd=%s\n",cmd));
		ret = smbrun(cmd,NULL);
		TALLOC_FREE(cmd);
		if (ret != 0 && lp_root_preexec_close(snum)) {
			DEBUG(1,("root preexec gave %d - failing "
				 "connection\n", ret));
			status = NT_STATUS_ACCESS_DENIED;
			goto err_root_exit;
		}
	}

/* USER Activites: */
	if (!change_to_user(conn, conn->vuid)) {
		/* No point continuing if they fail the basic checks */
		DEBUG(0,("Can't become connected user!\n"));
		status = NT_STATUS_LOGON_FAILURE;
		goto err_root_exit;
	}

	effuid = geteuid();
	effgid = getegid();

	/* Remember that a different vuid can connect later without these
	 * checks... */

	/* Preexecs are done here as they might make the dir we are to ChDir
	 * to below */

	/* execute any "preexec = " line */
	if (*lp_preexec(talloc_tos(), snum)) {
		char *cmd = talloc_sub_advanced(talloc_tos(),
					lp_servicename(talloc_tos(), SNUM(conn)),
					conn->session_info->unix_info->unix_name,
					conn->connectpath,
					conn->session_info->unix_token->gid,
					conn->session_info->unix_info->sanitized_username,
					conn->session_info->info->domain_name,
					lp_preexec(talloc_tos(), snum));
		ret = smbrun(cmd,NULL);
		TALLOC_FREE(cmd);
		if (ret != 0 && lp_preexec_close(snum)) {
			DEBUG(1,("preexec gave %d - failing connection\n",
				 ret));
			status = NT_STATUS_ACCESS_DENIED;
			goto err_root_exit;
		}
	}

#ifdef WITH_FAKE_KASERVER
	if (lp_afs_share(snum)) {
		afs_login(conn);
	}
#endif

	/*
	 * we've finished with the user stuff - go back to root
	 * so the SMB_VFS_STAT call will only fail on path errors,
	 * not permission problems.
	 */
	change_to_root_user();
/* ROOT Activites: */

	/*
	 * If widelinks are disallowed we need to canonicalise the connect
	 * path here to ensure we don't have any symlinks in the
	 * connectpath. We will be checking all paths on this connection are
	 * below this directory. We must do this after the VFS init as we
	 * depend on the realpath() pointer in the vfs table. JRA.
	 */
	if (!lp_widelinks(snum)) {
		if (!canonicalize_connect_path(conn)) {
			DEBUG(0, ("canonicalize_connect_path failed "
			"for service %s, path %s\n",
				lp_servicename(talloc_tos(), snum),
				conn->connectpath));
			status = NT_STATUS_BAD_NETWORK_NAME;
			goto err_root_exit;
		}
	}

	/* Add veto/hide lists */
	if (!IS_IPC(conn) && !IS_PRINT(conn)) {
		set_namearray( &conn->veto_list,
			       lp_veto_files(talloc_tos(), snum));
		set_namearray( &conn->hide_list,
			       lp_hide_files(talloc_tos(), snum));
		set_namearray( &conn->veto_oplock_list,
			       lp_veto_oplock_files(talloc_tos(), snum));
		set_namearray( &conn->aio_write_behind_list,
				lp_aio_write_behind(talloc_tos(), snum));
	}
	smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
					      NULL, NULL);
	if (smb_fname_cpath == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto err_root_exit;
	}

	/* win2000 does not check the permissions on the directory
	   during the tree connect, instead relying on permission
	   check during individual operations. To match this behaviour
	   I have disabled this chdir check (tridge) */
	/* the alternative is just to check the directory exists */

	if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
	    !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
		if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
			DEBUG(0,("'%s' is not a directory, when connecting to "
				 "[%s]\n", conn->connectpath,
				 lp_servicename(talloc_tos(), snum)));
		} else {
			DEBUG(0,("'%s' does not exist or permission denied "
				 "when connecting to [%s] Error was %s\n",
				 conn->connectpath,
				 lp_servicename(talloc_tos(), snum),
				 strerror(errno) ));
		}
		status = NT_STATUS_BAD_NETWORK_NAME;
		goto err_root_exit;
	}
	conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;

	talloc_free(conn->origpath);
	conn->origpath = talloc_strdup(conn, conn->connectpath);

	/* Figure out the characteristics of the underlying filesystem. This
	 * assumes that all the filesystem mounted withing a share path have
	 * the same characteristics, which is likely but not guaranteed.
	 */

	conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);

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

	if( DEBUGLVL( IS_IPC(conn) ? 3 : 2 ) ) {
		dbgtext( "%s (%s) ", get_remote_machine_name(),
			 tsocket_address_string(conn->sconn->remote_address,
						talloc_tos()) );
		dbgtext( "%s", srv_is_signing_active(xconn) ? "signed " : "");
		dbgtext( "connect to service %s ",
			 lp_servicename(talloc_tos(), snum) );
		dbgtext( "initially as user %s ",
			 conn->session_info->unix_info->unix_name );
		dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
		dbgtext( "(pid %d)\n", (int)getpid() );
	}

	return status;

  err_root_exit:

	TALLOC_FREE(smb_fname_cpath);
	/* We must exit this function as root. */
	if (geteuid() != 0) {
		change_to_root_user();
	}
	if (on_err_call_dis_hook) {
		/* Call VFS disconnect hook */
		SMB_VFS_DISCONNECT(conn);
	}
	return status;
}
Пример #11
0
/*****************************************************************************
 For idmap conversion: convert one record to new format
 Ancient versions (eg 2.2.3a) of winbindd_idmap.tdb mapped DOMAINNAME/rid
 instead of the SID.
*****************************************************************************/
static int convert_fn(struct db_record *rec, void *private_data)
{
	struct winbindd_domain *domain;
	char *p;
	NTSTATUS status;
	struct dom_sid sid;
	uint32 rid;
	fstring keystr;
	fstring dom_name;
	TDB_DATA key;
	TDB_DATA key2;
	TDB_DATA value;
	struct convert_fn_state *s = (struct convert_fn_state *)private_data;

	key = dbwrap_record_get_key(rec);

	DEBUG(10,("Converting %s\n", (const char *)key.dptr));

	p = strchr((const char *)key.dptr, '/');
	if (!p)
		return 0;

	*p = 0;
	fstrcpy(dom_name, (const char *)key.dptr);
	*p++ = '/';

	domain = find_domain_from_name(dom_name);
	if (domain == NULL) {
		/* We must delete the old record. */
		DEBUG(0,("Unable to find domain %s\n", dom_name ));
		DEBUG(0,("deleting record %s\n", (const char *)key.dptr ));

		status = dbwrap_record_delete(rec);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(0, ("Unable to delete record %s:%s\n",
				(const char *)key.dptr,
				nt_errstr(status)));
			s->failed = true;
			return -1;
		}

		return 0;
	}

	rid = atoi(p);

	sid_compose(&sid, &domain->sid, rid);

	sid_to_fstring(keystr, &sid);
	key2 = string_term_tdb_data(keystr);

	value = dbwrap_record_get_value(rec);

	status = dbwrap_store(s->db, key2, value, TDB_INSERT);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("Unable to add record %s:%s\n",
			(const char *)key2.dptr,
			nt_errstr(status)));
		s->failed = true;
		return -1;
	}

	status = dbwrap_store(s->db, value, key2, TDB_REPLACE);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("Unable to update record %s:%s\n",
			(const char *)value.dptr,
			nt_errstr(status)));
		s->failed = true;
		return -1;
	}

	status = dbwrap_record_delete(rec);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("Unable to delete record %s:%s\n",
			(const char *)key.dptr,
			nt_errstr(status)));
		s->failed = true;
		return -1;
	}

	return 0;
}
Пример #12
0
connection_struct *make_connection(struct smb_request *req,
				   NTTIME now,
				   const char *service_in,
				   const char *pdev, uint64_t vuid,
				   NTSTATUS *status)
{
	struct smbd_server_connection *sconn = req->sconn;
	uid_t euid;
	struct user_struct *vuser = NULL;
	char *service = NULL;
	fstring dev;
	int snum = -1;

	fstrcpy(dev, pdev);

	/* This must ONLY BE CALLED AS ROOT. As it exits this function as
	 * root. */
	if (!non_root_mode() && (euid = geteuid()) != 0) {
		DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
			 "(%u)\n", (unsigned int)euid ));
		smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
	}

	if (conn_num_open(sconn) > 2047) {
		*status = NT_STATUS_INSUFF_SERVER_RESOURCES;
		return NULL;
	}

	vuser = get_valid_user_struct(sconn, vuid);
	if (!vuser) {
		DEBUG(1,("make_connection: refusing to connect with "
			 "no session setup\n"));
		*status = NT_STATUS_ACCESS_DENIED;
		return NULL;
	}

	/* Logic to try and connect to the correct [homes] share, preferably
	   without too many getpwnam() lookups.  This is particulary nasty for
	   winbind usernames, where the share name isn't the same as unix
	   username.

	   The snum of the homes share is stored on the vuser at session setup
	   time.
	*/

	if (strequal(service_in,HOMES_NAME)) {
		if (vuser->homes_snum == -1) {
			DEBUG(2, ("[homes] share not available for "
				  "this user because it was not found "
				  "or created at session setup "
				  "time\n"));
			*status = NT_STATUS_BAD_NETWORK_NAME;
			return NULL;
		}
		DEBUG(5, ("making a connection to [homes] service "
			  "created at session setup time\n"));
		return make_connection_smb1(req, now,
					    vuser->homes_snum,
					    vuser,
					    dev, status);
	} else if ((vuser->homes_snum != -1)
		   && strequal(service_in,
			       lp_servicename(talloc_tos(), vuser->homes_snum))) {
		DEBUG(5, ("making a connection to 'homes' service [%s] "
			  "created at session setup time\n", service_in));
		return make_connection_smb1(req, now,
					    vuser->homes_snum,
					    vuser,
					    dev, status);
	}

	service = talloc_strdup(talloc_tos(), service_in);
	if (!service) {
		*status = NT_STATUS_NO_MEMORY;
		return NULL;
	}

	if (!strlower_m(service)) {
		DEBUG(2, ("strlower_m %s failed\n", service));
		*status = NT_STATUS_INVALID_PARAMETER;
		return NULL;
	}

	snum = find_service(talloc_tos(), service, &service);
	if (!service) {
		*status = NT_STATUS_NO_MEMORY;
		return NULL;
	}

	if (snum < 0) {
		if (strequal(service,"IPC$") ||
		    (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
			DEBUG(3,("refusing IPC connection to %s\n", service));
			*status = NT_STATUS_ACCESS_DENIED;
			return NULL;
		}

		DEBUG(3,("%s (%s) couldn't find service %s\n",
			get_remote_machine_name(),
			tsocket_address_string(
				sconn->remote_address, talloc_tos()),
			service));
		*status = NT_STATUS_BAD_NETWORK_NAME;
		return NULL;
	}

	/* Handle non-Dfs clients attempting connections to msdfs proxy */
	if (lp_host_msdfs() && (*lp_msdfs_proxy(talloc_tos(), snum) != '\0'))  {
		DEBUG(3, ("refusing connection to dfs proxy share '%s' "
			  "(pointing to %s)\n", 
			service, lp_msdfs_proxy(talloc_tos(), snum)));
		*status = NT_STATUS_BAD_NETWORK_NAME;
		return NULL;
	}

	DEBUG(5, ("making a connection to 'normal' service %s\n", service));

	return make_connection_smb1(req, now, snum, vuser,
				    dev, status);
}
Пример #13
0
void process_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
{
	struct dgram_packet *dgram = &p->packet.dgram;
	int ttl = IVAL(buf,1)/1000;
	unstring announce_name;
	uint32 servertype = IVAL(buf,23);
	fstring comment;
	struct work_record *work;
	struct server_record *servrec;
	unstring work_name;
	unstring source_name;

	START_PROFILE(host_announce);

	pull_ascii_fstring(comment, buf+31);
  
	pull_ascii_nstring(announce_name, sizeof(announce_name), buf+5);
	pull_ascii_nstring(source_name, sizeof(source_name), dgram->source_name.name);

	DEBUG(3,("process_host_announce: from %s<%02x> IP %s to \
%s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip),
			nmb_namestr(&dgram->dest_name),announce_name));

	DEBUG(5,("process_host_announce: ttl=%d server type=%08x comment=%s\n",
		ttl, servertype,comment));

	/* Filter servertype to remove impossible bits. */
	servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);

	/* A host announcement must be sent to the name WORKGROUP<1d>. */
	if(dgram->dest_name.name_type != 0x1d) {
		DEBUG(2,("process_host_announce: incorrect name type for destination from IP %s \
(was %02x) should be 0x1d. Allowing packet anyway.\n",
			inet_ntoa(p->ip), dgram->dest_name.name_type));
		/* Change it so it was. */
		dgram->dest_name.name_type = 0x1d;
	}

	/* For a host announce the workgroup name is the destination name. */
	pull_ascii_nstring(work_name, sizeof(work_name), dgram->dest_name.name);

	/*
	 * Syntax servers version 5.1 send HostAnnounce packets to
	 * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00>
	 * instead of WORKGROUP<1d> name. So to fix this we check if
	 * the workgroup name is our own name, and if so change it
	 * to be our primary workgroup name.
	 */

	if(strequal(work_name, global_myname()))
		unstrcpy(work_name,lp_workgroup());

	/*
	 * We are being very agressive here in adding a workgroup
	 * name on the basis of a host announcing itself as being
	 * in that workgroup. Maybe we should wait for the workgroup
	 * announce instead ? JRA.
	 */

	work = find_workgroup_on_subnet(subrec, work_name);

	if(servertype != 0) {
		if (work ==NULL ) {
			/* We have no record of this workgroup. Add it. */
			if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)
				goto done;
		}
  
		if((servrec = find_server_in_workgroup( work, announce_name))==NULL) {
			/* If this server is not already in the workgroup, add it. */
			create_server_on_workgroup(work, announce_name, 
				servertype|SV_TYPE_LOCAL_LIST_ONLY, 
				ttl, comment);
		} else {
			/* Update the record. */
			servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;
			update_server_ttl( servrec, ttl);
			fstrcpy(servrec->serv.comment,comment);
		}
	} else {
		/*
		 * This server is announcing it is going down. Remove it from the 
		 * workgroup.
		 */
		if(!is_myname(announce_name) && (work != NULL) &&
				((servrec = find_server_in_workgroup( work, announce_name))!=NULL)) {
			remove_server_from_workgroup( work, servrec);
		}
	}

	subrec->work_changed = True;
done:

	END_PROFILE(host_announce);
}
Пример #14
0
void process_local_master_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
{
	struct dgram_packet *dgram = &p->packet.dgram;
	int ttl = IVAL(buf,1)/1000;
	unstring server_name;
	uint32 servertype = IVAL(buf,23);
	fstring comment;
	unstring work_name;
	struct work_record *work;
	struct server_record *servrec;
	unstring source_name;

	START_PROFILE(local_master_announce);

	pull_ascii_nstring(server_name,sizeof(server_name),buf+5);
	pull_ascii_fstring(comment, buf+31);
	pull_ascii_nstring(source_name, sizeof(source_name), dgram->source_name.name);
	pull_ascii_nstring(work_name, sizeof(work_name), dgram->dest_name.name);

	DEBUG(3,("process_local_master_announce: from %s<%02x> IP %s to \
%s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip),
		nmb_namestr(&dgram->dest_name),server_name));

	DEBUG(5,("process_local_master_announce: ttl=%d server type=%08x comment=%s\n",
		ttl, servertype, comment));

	/* A local master announcement must be sent to the name WORKGROUP<1e>. */
	if(dgram->dest_name.name_type != 0x1e) {
		DEBUG(0,("process_local_master_announce: incorrect name type for destination from IP %s \
(was %02x) should be 0x1e. Ignoring packet.\n",
			inet_ntoa(p->ip), dgram->dest_name.name_type));
		goto done;
	}

	/* Filter servertype to remove impossible bits. */
	servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);

	/* For a local master announce the workgroup name is the destination name. */

	if ((work = find_workgroup_on_subnet(subrec, work_name))==NULL) {
		/* Don't bother adding if it's a local master release announce. */
		if(servertype == 0)
			goto done;

		/* We have no record of this workgroup. Add it. */
		if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)
			goto done;
	}

	/* If we think we're the local master browser for this workgroup,
		we should never have got this packet. We don't see our own
		packets.
	*/
	if(AM_LOCAL_MASTER_BROWSER(work)) {
		DEBUG(0,("process_local_master_announce: Server %s at IP %s is announcing itself as \
a local master browser for workgroup %s and we think we are master. Forcing election.\n",
			server_name, inet_ntoa(p->ip), work_name));

		/* Samba nmbd versions 1.9.17 to 1.9.17p4 have a bug in that when
		 they have become a local master browser once, they will never
		 stop sending local master announcements. To fix this we send
		 them a reset browser packet, with level 0x2 on the __SAMBA__
		 name that only they should be listening to. */
   
		send_browser_reset( 0x2, "__SAMBA__" , 0x20, p->ip);

		/* We should demote ourself and force an election. */

		unbecome_local_master_browser( subrec, work, True);

		/* The actual election requests are handled in nmbd_election.c */
		goto done;
	}  

	/* Find the server record on this workgroup. If it doesn't exist, add it. */

	if(servertype != 0) {
		if((servrec = find_server_in_workgroup( work, server_name))==NULL) {
			/* If this server is not already in the workgroup, add it. */
			create_server_on_workgroup(work, server_name, 
				servertype|SV_TYPE_LOCAL_LIST_ONLY, 
				ttl, comment);
		} else {
			/* Update the record. */
			servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;
			update_server_ttl(servrec, ttl);
			fstrcpy(servrec->serv.comment,comment);
		}
	
		set_workgroup_local_master_browser_name( work, server_name );
	} else {
		/*
		 * This server is announcing it is going down. Remove it from the
		 * workgroup.
		 */
		if(!is_myname(server_name) && (work != NULL) &&
				((servrec = find_server_in_workgroup( work, server_name))!=NULL)) {
			remove_server_from_workgroup( work, servrec);
		}
	}

	subrec->work_changed = True;
done:

	END_PROFILE(local_master_announce);
}
Пример #15
0
static void sync_child(char *name, int nm_type, 
		       char *workgroup,
		       struct in_addr ip, bool local, bool servers,
		       char *fname)
{
	fstring unix_workgroup;
	struct cli_state *cli;
	uint32 local_type = local ? SV_TYPE_LOCAL_LIST_ONLY : 0;
	struct nmb_name called, calling;
	struct sockaddr_storage ss;
	NTSTATUS status;

	/* W2K DMB's return empty browse lists on port 445. Use 139.
	 * Patch from Andy Levine [email protected].
	 */

	cli = cli_initialise();
	if (!cli) {
		return;
	}

	cli_set_port(cli, 139);

	in_addr_to_sockaddr_storage(&ss, ip);
	status = cli_connect(cli, name, &ss);
	if (!NT_STATUS_IS_OK(status)) {
		cli_shutdown(cli);
		return;
	}

	make_nmb_name(&calling, get_local_machine_name(), 0x0);
	make_nmb_name(&called , name, nm_type);

	if (!cli_session_request(cli, &calling, &called)) {
		cli_shutdown(cli);
		return;
	}

	status = cli_negprot(cli);
	if (!NT_STATUS_IS_OK(status)) {
		cli_shutdown(cli);
		return;
	}

	if (!NT_STATUS_IS_OK(cli_session_setup(cli, "", "", 1, "", 0,
					       workgroup))) {
		cli_shutdown(cli);
		return;
	}

	if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, "IPC$", "IPC", "", 1))) {
		cli_shutdown(cli);
		return;
	}

	/* All the cli_XX functions take UNIX character set. */
	fstrcpy(unix_workgroup, cli->server_domain ? cli->server_domain : workgroup);

	/* Fetch a workgroup list. */
	cli_NetServerEnum(cli, unix_workgroup,
			  local_type|SV_TYPE_DOMAIN_ENUM, 
			  callback, NULL);
	
	/* Now fetch a server list. */
	if (servers) {
		fstrcpy(unix_workgroup, workgroup);
		cli_NetServerEnum(cli, unix_workgroup, 
				  local?SV_TYPE_LOCAL_LIST_ONLY:SV_TYPE_ALL,
				  callback, NULL);
	}
	
	cli_shutdown(cli);
}
Пример #16
0
struct tdb_print_db *get_print_db_byname(const char *printername)
{
	struct tdb_print_db *p = NULL, *last_entry = NULL;
	int num_open = 0;
	pstring printdb_path;
	BOOL done_become_root = False;

	for (p = print_db_head, last_entry = print_db_head; p; p = p->next) {
		/* Ensure the list terminates... JRA. */
		SMB_ASSERT(p->next != print_db_head);

		if (p->tdb && strequal(p->printer_name, printername)) {
			DLIST_PROMOTE(print_db_head, p);
			p->ref_count++;
			return p;
		}
		num_open++;
		last_entry = p;
	}

	/* Not found. */
	if (num_open >= MAX_PRINT_DBS_OPEN) {
		/* Try and recycle the last entry. */
		DLIST_PROMOTE(print_db_head, last_entry);

		for (p = print_db_head; p; p = p->next) {
			if (p->ref_count)
				continue;
			if (p->tdb) {
				if (tdb_close(print_db_head->tdb)) {
					DEBUG(0,("get_print_db: Failed to close tdb for printer %s\n",
								print_db_head->printer_name ));
					return NULL;
				}
			}
			p->tdb = NULL;
			p->ref_count = 0;
			memset(p->printer_name, '\0', sizeof(p->printer_name));
			break;
		}
		if (p) {
			DLIST_PROMOTE(print_db_head, p);
			p = print_db_head;
		}
	}
       
	if (!p)	{
		/* Create one. */
		p = (struct tdb_print_db *)malloc(sizeof(struct tdb_print_db));
		if (!p) {
			DEBUG(0,("get_print_db: malloc fail !\n"));
			return NULL;
		}
		ZERO_STRUCTP(p);
		DLIST_ADD(print_db_head, p);
	}

	pstrcpy(printdb_path, lock_path("printing/"));
	pstrcat(printdb_path, printername);
	pstrcat(printdb_path, ".tdb");

	if (geteuid() != 0) {
		become_root();
		done_become_root = True;
	}

	p->tdb = tdb_open_log(printdb_path, 5000, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);

	if (done_become_root)
		unbecome_root();

	if (!p->tdb) {
		DEBUG(0,("get_print_db: Failed to open printer backend database %s.\n",
					printdb_path ));
		DLIST_REMOVE(print_db_head, p);
		SAFE_FREE(p);
		return NULL;
	}
	fstrcpy(p->printer_name, printername);
	p->ref_count++;
	return p;
}
Пример #17
0
int register_vuid(auth_serversupplied_info *server_info,
		  DATA_BLOB session_key, DATA_BLOB response_blob,
		  const char *smb_name)
{
	user_struct *vuser = NULL;

	/* Paranoia check. */
	if(lp_security() == SEC_SHARE) {
		smb_panic("Tried to register uid in security=share\n");
	}

	/* Limit allowed vuids to 16bits - VUID_OFFSET. */
	if (num_validated_vuids >= 0xFFFF-VUID_OFFSET) {
		data_blob_free(&session_key);
		return UID_FIELD_INVALID;
	}

	if((vuser = SMB_MALLOC_P(user_struct)) == NULL) {
		DEBUG(0,("Failed to malloc users struct!\n"));
		data_blob_free(&session_key);
		return UID_FIELD_INVALID;
	}

	ZERO_STRUCTP(vuser);

	/* Allocate a free vuid. Yes this is a linear search... :-) */
	while( get_valid_user_struct(next_vuid) != NULL ) {
		next_vuid++;
		/* Check for vuid wrap. */
		if (next_vuid == UID_FIELD_INVALID)
			next_vuid = VUID_OFFSET;
	}

	DEBUG(10,("register_vuid: allocated vuid = %u\n",
		  (unsigned int)next_vuid ));

	vuser->vuid = next_vuid;

	if (!server_info) {
		/*
		 * This happens in an unfinished NTLMSSP session setup. We
		 * need to allocate a vuid between the first and second calls
		 * to NTLMSSP.
		 */
		next_vuid++;
		num_validated_vuids++;
		
		vuser->server_info = NULL;
		
		DLIST_ADD(validated_users, vuser);
		
		return vuser->vuid;
	}

	/* the next functions should be done by a SID mapping system (SMS) as
	 * the new real sam db won't have reference to unix uids or gids
	 */
	
	vuser->uid = server_info->uid;
	vuser->gid = server_info->gid;
	
	vuser->n_groups = server_info->n_groups;
	if (vuser->n_groups) {
		if (!(vuser->groups = (gid_t *)memdup(server_info->groups,
						      sizeof(gid_t) *
						      vuser->n_groups))) {
			DEBUG(0,("register_vuid: failed to memdup "
				 "vuser->groups\n"));
			data_blob_free(&session_key);
			free(vuser);
			TALLOC_FREE(server_info);
			return UID_FIELD_INVALID;
		}
	}

	vuser->guest = server_info->guest;
	fstrcpy(vuser->user.unix_name, server_info->unix_name); 

	/* This is a potentially untrusted username */
	alpha_strcpy(vuser->user.smb_name, smb_name, ". _-$",
		     sizeof(vuser->user.smb_name));

	fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account));
	fstrcpy(vuser->user.full_name,
		pdb_get_fullname(server_info->sam_account));

	{
		/* Keep the homedir handy */
		const char *homedir =
			pdb_get_homedir(server_info->sam_account);
		const char *logon_script =
			pdb_get_logon_script(server_info->sam_account);

		if (!IS_SAM_DEFAULT(server_info->sam_account,
				    PDB_UNIXHOMEDIR)) {
			const char *unix_homedir =
				pdb_get_unix_homedir(server_info->sam_account);
			if (unix_homedir) {
				vuser->unix_homedir =
					smb_xstrdup(unix_homedir);
			}
		} else {
			struct passwd *passwd =
				getpwnam_alloc(NULL, vuser->user.unix_name);
			if (passwd) {
				vuser->unix_homedir =
					smb_xstrdup(passwd->pw_dir);
				TALLOC_FREE(passwd);
			}
		}
		
		if (homedir) {
			vuser->homedir = smb_xstrdup(homedir);
		}
		if (logon_script) {
			vuser->logon_script = smb_xstrdup(logon_script);
		}
	}

	vuser->session_key = session_key;

	DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n", 
		  (unsigned int)vuser->uid, 
		  (unsigned int)vuser->gid,
		  vuser->user.unix_name, vuser->user.smb_name,
		  vuser->user.domain, vuser->guest ));

	DEBUG(3, ("User name: %s\tReal name: %s\n", vuser->user.unix_name,
		  vuser->user.full_name));	

 	if (server_info->ptok) {
		vuser->nt_user_token = dup_nt_token(NULL, server_info->ptok);
	} else {
		DEBUG(1, ("server_info does not contain a user_token - "
			  "cannot continue\n"));
		TALLOC_FREE(server_info);
		data_blob_free(&session_key);
		SAFE_FREE(vuser->homedir);
		SAFE_FREE(vuser->unix_homedir);
		SAFE_FREE(vuser->logon_script);

		SAFE_FREE(vuser);
		return UID_FIELD_INVALID;
	}

	/* use this to keep tabs on all our info from the authentication */
	vuser->server_info = server_info;

	DEBUG(3,("UNIX uid %d is UNIX user %s, and will be vuid %u\n",
		 (int)vuser->uid,vuser->user.unix_name, vuser->vuid));

	next_vuid++;
	num_validated_vuids++;

	DLIST_ADD(validated_users, vuser);

	if (!session_claim(vuser)) {
		DEBUG(1, ("Failed to claim session for vuid=%d\n",
			  vuser->vuid));
		invalidate_vuid(vuser->vuid);
		return UID_FIELD_INVALID;
	}

	/* Register a home dir service for this user iff
	
	   (a) This is not a guest connection,
	   (b) we have a home directory defined 
	   (c) there s not an existing static share by that name
	   
	   If a share exists by this name (autoloaded or not) reuse it . */

	vuser->homes_snum = -1;

	if ( (!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)) 
	{
		int servicenumber = lp_servicenumber(vuser->user.unix_name);

		if ( servicenumber == -1 ) {
			DEBUG(3, ("Adding homes service for user '%s' using "
				  "home directory: '%s'\n", 
				vuser->user.unix_name, vuser->unix_homedir));
			vuser->homes_snum =
				add_home_service(vuser->user.unix_name, 
						 vuser->user.unix_name,
						 vuser->unix_homedir);
		} else {
			DEBUG(3, ("Using static (or previously created) "
				  "service for user '%s'; path = '%s'\n", 
				  vuser->user.unix_name,
				  lp_pathname(servicenumber) ));
			vuser->homes_snum = servicenumber;
		}
	} 
	
	if (srv_is_signing_negotiated() && !vuser->guest &&
	    !srv_signing_started()) {
		/* Try and turn on server signing on the first non-guest
		 * sessionsetup. */
		srv_set_signing(vuser->session_key, response_blob);
	}
	
	/* fill in the current_user_info struct */
	set_current_user_info( &vuser->user );


	return vuser->vuid;
}
Пример #18
0
/****************************************************************************
  main program
****************************************************************************/
int main(int argc,char *argv[])
{
	int opt;
	unsigned int lookup_type = 0x0;
	fstring lookup;
	static bool find_master=False;
	static bool lookup_by_ip = False;
	poptContext pc;
	TALLOC_CTX *frame = talloc_stackframe();

	struct poptOption long_options[] = {
		POPT_AUTOHELP
		{ "broadcast", 'B', POPT_ARG_STRING, NULL, 'B', "Specify address to use for broadcasts", "BROADCAST-ADDRESS" },
		{ "flags", 'f', POPT_ARG_NONE, NULL, 'f', "List the NMB flags returned" },
		{ "unicast", 'U', POPT_ARG_STRING, NULL, 'U', "Specify address to use for unicast" },
		{ "master-browser", 'M', POPT_ARG_NONE, NULL, 'M', "Search for a master browser" },
		{ "recursion", 'R', POPT_ARG_NONE, NULL, 'R', "Set recursion desired in package" },
		{ "status", 'S', POPT_ARG_NONE, NULL, 'S', "Lookup node status as well" },
		{ "translate", 'T', POPT_ARG_NONE, NULL, 'T', "Translate IP addresses into names" },
		{ "root-port", 'r', POPT_ARG_NONE, NULL, 'r', "Use root port 137 (Win95 only replies to this)" },
		{ "lookup-by-ip", 'A', POPT_ARG_NONE, NULL, 'A', "Do a node status on <name> as an IP Address" },
		POPT_COMMON_SAMBA
		POPT_COMMON_CONNECTION
		{ 0, 0, 0, 0 }
	};

	*lookup = 0;

	load_case_tables();

	setup_logging(argv[0], DEBUG_STDOUT);

	pc = poptGetContext("nmblookup", argc, (const char **)argv,
			long_options, POPT_CONTEXT_KEEP_FIRST);

	poptSetOtherOptionHelp(pc, "<NODE> ...");

	while ((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt) {
		case 'f':
			give_flags = true;
			break;
		case 'M':
			find_master = true;
			break;
		case 'R':
			recursion_desired = true;
			break;
		case 'S':
			find_status = true;
			break;
		case 'r':
			RootPort = true;
			break;
		case 'A':
			lookup_by_ip = true;
			break;
		case 'B':
			if (interpret_string_addr(&bcast_addr,
					poptGetOptArg(pc),
					NI_NUMERICHOST)) {
				got_bcast = True;
				use_bcast = True;
			}
			break;
		case 'U':
			if (interpret_string_addr(&bcast_addr,
					poptGetOptArg(pc),
					0)) {
				got_bcast = True;
				use_bcast = False;
			}
			break;
		case 'T':
			translate_addresses = !translate_addresses;
			break;
		}
	}

	poptGetArg(pc); /* Remove argv[0] */

	if(!poptPeekArg(pc)) {
		poptPrintUsage(pc, stderr, 0);
		exit(1);
	}

	if (!lp_load(get_dyn_CONFIGFILE(),True,False,False,True)) {
		fprintf(stderr, "Can't load %s - run testparm to debug it\n",
				get_dyn_CONFIGFILE());
	}

	load_interfaces();
	if (!open_sockets()) {
		return(1);
	}

	while(poptPeekArg(pc)) {
		char *p;
		struct in_addr ip;

		fstrcpy(lookup,poptGetArg(pc));

		if(lookup_by_ip) {
			struct sockaddr_storage ss;
			ip = interpret_addr2(lookup);
			in_addr_to_sockaddr_storage(&ss, ip);
			fstrcpy(lookup,"*");
			do_node_status(lookup, lookup_type, &ss);
			continue;
		}

		if (find_master) {
			if (*lookup == '-') {
				fstrcpy(lookup,"\01\02__MSBROWSE__\02");
				lookup_type = 1;
			} else {
				lookup_type = 0x1d;
			}
		}

		p = strchr_m(lookup,'#');
		if (p) {
			*p = '\0';
			sscanf(++p,"%x",&lookup_type);
		}

		if (!query_one(lookup, lookup_type)) {
			d_printf( "name_query failed to find name %s", lookup );
			if( 0 != lookup_type ) {
				d_printf( "#%02x", lookup_type );
			}
			d_printf( "\n" );
		}
	}

	poptFreeContext(pc);
	TALLOC_FREE(frame);
	return(0);
}
Пример #19
0
BOOL authorise_login(int snum, fstring user, DATA_BLOB password, 
		     BOOL *guest)
{
	BOOL ok = False;
	
#ifdef DEBUG_PASSWORD
	DEBUG(100,("authorise_login: checking authorisation on "
		   "user=%s pass=%s\n", user,password.data));
#endif

	*guest = False;
  
	/* there are several possibilities:
		1) login as the given user with given password
		2) login as a previously registered username with the given 
		   password
		3) login as a session list username with the given password
		4) login as a previously validated user/password pair
		5) login as the "user ="******"user ="******"");

		if (!user_list)
			return(False);
		
		for (auser=strtok(user_list,LIST_SEP); !ok && auser;
		     auser = strtok(NULL,LIST_SEP)) {
			fstring user2;
			fstrcpy(user2,auser);
			if (!user_ok(user2,snum))
				continue;
			
			if (password_ok(user2,password)) {
				ok = True;
				fstrcpy(user,user2);
				DEBUG(3,("authorise_login: ACCEPTED: session "
					 "list username (%s) and given "
					 "password ok\n", user));
			}
		}

		SAFE_FREE(user_list);
	}
	
	/* check the user= fields and the given password */
	if (!ok && lp_username(snum)) {
		char *auser;
		pstring user_list;
		pstrcpy(user_list,lp_username(snum));
		
		pstring_sub(user_list,"%S",lp_servicename(snum));
		
		for (auser=strtok(user_list,LIST_SEP); auser && !ok;
		     auser = strtok(NULL,LIST_SEP)) {
			if (*auser == '@') {
				auser = validate_group(auser+1,password,snum);
				if (auser) {
					ok = True;
					fstrcpy(user,auser);
					DEBUG(3,("authorise_login: ACCEPTED: "
						 "group username and given "
						 "password ok (%s)\n", user));
				}
			} else {
				fstring user2;
				fstrcpy(user2,auser);
				if (user_ok(user2,snum) &&
				    password_ok(user2,password)) {
					ok = True;
					fstrcpy(user,user2);
					DEBUG(3,("authorise_login: ACCEPTED: "
						 "user list username and "
						 "given password ok (%s)\n",
						 user));
				}
			}
		}
	}

	/* check for a normal guest connection */
	if (!ok && GUEST_OK(snum)) {
		fstring guestname;
		fstrcpy(guestname,lp_guestaccount());
		if (Get_Pwnam(guestname)) {
			fstrcpy(user,guestname);
			ok = True;
			DEBUG(3,("authorise_login: ACCEPTED: guest account "
				 "and guest ok (%s)\n",	user));
		} else {
			DEBUG(0,("authorise_login: Invalid guest account "
				 "%s??\n",guestname));
		}
		*guest = True;
	}

	if (ok && !user_ok(user, snum)) {
		DEBUG(0,("authorise_login: rejected invalid user %s\n",user));
		ok = False;
	}

	return(ok);
}
Пример #20
0
static void wins_registration_timeout(struct subnet_record *subrec,
				      struct response_record *rrec)
{
	struct userdata_struct *userdata = rrec->userdata;
	struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
	struct nmb_name *nmbname = &sent_nmb->question.question_name;
	struct in_addr register_ip;
	fstring src_addr;

	putip(&register_ip,&sent_nmb->additional->rdata[2]);

	fstrcpy(src_addr, inet_ntoa(register_ip));

	DEBUG(2,("wins_registration_timeout: WINS server %s timed out registering IP %s\n", 
		 inet_ntoa(rrec->packet->ip), src_addr));

	/* mark it temporarily dead for this source address */
	wins_srv_died(rrec->packet->ip, register_ip);

	/* if we have some userdata then use that to work out what
	   wins server to try next */
	if (userdata) {
		const char *tag = (const char *)userdata->data;

		/* try the next wins server in our failover list for
		   this tag */
		rrec->packet->ip = wins_srv_ip_tag(tag, register_ip);
	}

	/* if we have run out of wins servers for this tag then they
	   must all have timed out. We treat this as *success*, not
	   failure, and go into our standard name refresh mode. This
	   copes with all the wins servers being down */
	if (wins_srv_is_dead(rrec->packet->ip, register_ip)) {
		uint16_t nb_flags = get_nb_flags(sent_nmb->additional->rdata);
		int ttl = sent_nmb->additional->ttl;

		standard_success_register(subrec, userdata, nmbname, nb_flags, ttl, register_ip);
		if(rrec->success_fn) {
			(*(register_name_success_function)rrec->success_fn)(subrec, 
									    rrec->userdata, 
									    nmbname, 
									    nb_flags, 
									    ttl, 
									    register_ip);
		}

		/* send off a registration for the next IP, if any */
		wins_next_registration(rrec);

		/* don't need to send this packet any more */
		remove_response_record(subrec, rrec);
		return;
	}
	
	/* we will be moving to the next WINS server for this group,
	   send it immediately */
	rrec->repeat_count = 2;
	rrec->repeat_time = time(NULL) + 1;
	rrec->in_expiration_processing = False;

	DEBUG(6,("Retrying register of name %s IP %s with WINS server %s\n",
		 nmb_namestr(nmbname), src_addr, inet_ntoa(rrec->packet->ip)));

	/* notice that we don't remove the response record. This keeps
	   us trying to register with each of our failover wins servers */
}
Пример #21
0
enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state)
{
	NTSTATUS result;
	char *oldpass, *newpass;
	fstring domain, user;
	CLI_POLICY_HND *hnd;
	TALLOC_CTX *mem_ctx;
	struct winbindd_domain *contact_domain;

	DEBUG(3, ("[%5lu]: pam chauthtok %s\n", (unsigned long)state->pid,
		state->request.data.chauthtok.user));

	if (!(mem_ctx = talloc_init("winbind password change for (utf8) %s", 
				    state->request.data.chauthtok.user))) {
		DEBUG(0, ("winbindd_pam_auth_crap: could not talloc_init()!\n"));
		result = NT_STATUS_NO_MEMORY;
		goto done;
	}

	/* Setup crap */

	if (state == NULL)
		return WINBINDD_ERROR;

	parse_domain_user(state->request.data.chauthtok.user, domain, user);

	if (!(contact_domain = find_domain_from_name(domain))) {
		DEBUG(3, ("Cannot change password for [%s] -> [%s]\\[%s] as %s is not a trusted domain\n", 
			  state->request.data.chauthtok.user, domain, user, domain)); 
		result = NT_STATUS_NO_SUCH_USER;
		goto done;
	}

	/* Change password */

	oldpass = state->request.data.chauthtok.oldpass;
	newpass = state->request.data.chauthtok.newpass;

	/* Get sam handle */

	if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(contact_domain, &hnd)) ) {
		DEBUG(1, ("could not get SAM handle on DC for %s\n", domain));
		goto done;
	}

	result = cli_samr_chgpasswd_user(hnd->cli, mem_ctx, user, newpass, oldpass);

done:    
	state->response.data.auth.nt_status = NT_STATUS_V(result);
	fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
	fstrcpy(state->response.data.auth.error_string, nt_errstr(result));
	state->response.data.auth.pam_error = nt_status_to_pam(result);

	DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, 
	      ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n", 
	       domain,
	       user,
	       state->response.data.auth.nt_status_string,
	       state->response.data.auth.pam_error));	      

	if (mem_ctx)
		talloc_destroy(mem_ctx);

	return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
}
Пример #22
0
static void register_name_response(struct subnet_record *subrec,
                       struct response_record *rrec, struct packet_struct *p)
{
	/* 
	 * If we are registering broadcast, then getting a response is an
	 * error - we do not have the name. If we are registering unicast,
	 * then we expect to get a response.
	 */

	struct nmb_packet *nmb = &p->packet.nmb;
	bool bcast = nmb->header.nm_flags.bcast;
	bool success = True;
	struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
	struct nmb_name *answer_name = &nmb->answers->rr_name;
	struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
	int ttl = 0;
	uint16_t nb_flags = 0;
	struct in_addr register_ip;
	fstring reg_name;
	
	putip(&register_ip,&sent_nmb->additional->rdata[2]);
	fstrcpy(reg_name, inet_ntoa(register_ip));
	
	if (subrec == unicast_subnet) {
		/* we know that this wins server is definately alive - for the moment! */
		wins_srv_alive(rrec->packet->ip, register_ip);
	}

	/* Sanity check. Ensure that the answer name in the incoming packet is the
	   same as the requested name in the outgoing packet. */

	if(!question_name || !answer_name) {
		DEBUG(0,("register_name_response: malformed response (%s is NULL).\n",
			 question_name ? "question_name" : "answer_name" ));
		return;
	}

	if(!nmb_name_equal(question_name, answer_name)) {
		DEBUG(0,("register_name_response: Answer name %s differs from question name %s.\n", 
			 nmb_namestr(answer_name), nmb_namestr(question_name)));
		return;
	}

	if(bcast) {
		/*
		 * Special hack to cope with old Samba nmbd's.
		 * Earlier versions of Samba (up to 1.9.16p11) respond 
		 * to a broadcast name registration of WORKGROUP<1b> when 
		 * they should not. Hence, until these versions are gone, 
		 * we should treat such errors as success for this particular
		 * case only. [email protected].
		 */
		
#if 1 /* OLD_SAMBA_SERVER_HACK */
		unstring ans_name;
		pull_ascii_nstring(ans_name, sizeof(ans_name), answer_name->name);
		if((nmb->header.rcode == ACT_ERR) && strequal(lp_workgroup(), ans_name) &&
		   (answer_name->name_type == 0x1b)) {
			/* Pretend we did not get this. */
			rrec->num_msgs--;

			DEBUG(5,("register_name_response: Ignoring broadcast response to registration of name %s due to old Samba server bug.\n", 
				 nmb_namestr(answer_name)));
			return;
		}
#endif /* OLD_SAMBA_SERVER_HACK */

		/* Someone else has the name. Log the problem. */
		DEBUG(1,("register_name_response: Failed to register name %s IP %s on subnet %s via broadcast. Error code was %d. Reject came from IP %s\n", 
			 nmb_namestr(answer_name), 
			 reg_name,
			 subrec->subnet_name, nmb->header.rcode, inet_ntoa(p->ip)));
		success = False;
	} else {
		if (!ip_equal_v4(rrec->packet->ip, p->ip)) {
			DEBUG(5,("register_name_response: Ignoring WINS server response "
				"from IP %s, for name %s. We sent to IP %s\n",
				inet_ntoa(p->ip),
				nmb_namestr(answer_name),
				inet_ntoa(rrec->packet->ip)));
			return;
		}
		/* Unicast - check to see if the response allows us to have the name. */
		if (nmb->header.opcode == NMB_WACK_OPCODE) {
			/* WINS server is telling us to wait. Pretend we didn't get
			   the response but don't send out any more register requests. */

			DEBUG(5,("register_name_response: WACK from WINS server %s in registering name %s IP %s\n", 
				 inet_ntoa(p->ip), nmb_namestr(answer_name), reg_name));

			rrec->repeat_count = 0;
			/* How long we should wait for. */
			rrec->repeat_time = p->timestamp + nmb->answers->ttl;
			rrec->num_msgs--;
			return;
		} else if (nmb->header.rcode != 0) {
			/* Error code - we didn't get the name. */
			success = False;

			DEBUG(0,("register_name_response: %sserver at IP %s rejected our name registration of %s IP %s with error code %d.\n", 
				 subrec==unicast_subnet?"WINS ":"",
				 inet_ntoa(p->ip), 
				 nmb_namestr(answer_name), 
				 reg_name,
				 nmb->header.rcode));
		} else {
			success = True;
			/* Get the data we need to pass to the success function. */
			nb_flags = get_nb_flags(nmb->answers->rdata);
			ttl = nmb->answers->ttl;

			/* send off a registration for the next IP, if any */
			wins_next_registration(rrec);
		}
	} 

	DEBUG(5,("register_name_response: %s in registering %sname %s IP %s with %s.\n",
		 success ? "success" : "failure", 
		 subrec==unicast_subnet?"WINS ":"",
		 nmb_namestr(answer_name), 
		 reg_name,
		 inet_ntoa(rrec->packet->ip)));

	if(success) {
		/* Enter the registered name into the subnet name database before calling
		   the success function. */
		standard_success_register(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip);
		if( rrec->success_fn)
			(*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip);
	} else {
		struct nmb_name qname = *question_name;
		if( rrec->fail_fn)
			(*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
		/* Remove the name. */
		standard_fail_register( subrec, &qname);
	}

	/* Ensure we don't retry. */
	remove_response_record(subrec, rrec);
}
Пример #23
0
BOOL map_username(char *user)
{
  static BOOL initialised=False;
  static fstring last_from,last_to;
  FILE *f;
  char *mapfile = lp_username_map();
  char *s;
  pstring buf;
  BOOL mapped_user = False;

  if (!*user)
    return False;

  if (!*mapfile)
    return False;

  if (!initialised) {
    *last_from = *last_to = 0;
    initialised = True;
  }

  if (strequal(user,last_to))
    return False;

  if (strequal(user,last_from)) {
    DEBUG(3,("Mapped user %s to %s\n",user,last_to));
    fstrcpy(user,last_to);
    return True;
  }
  
  f = sys_fopen(mapfile,"r");
  if (!f) {
    DEBUG(0,("can't open username map %s\n",mapfile));
    return False;
  }

  DEBUG(4,("Scanning username map %s\n",mapfile));

  while((s=fgets_slash(buf,sizeof(buf),f))!=NULL) {
    char *unixname = s;
    char *dosname = strchr(unixname,'=');
    BOOL return_if_mapped = False;

    if (!dosname)
      continue;

    *dosname++ = 0;

    while (isspace(*unixname))
      unixname++;
    if ('!' == *unixname) {
      return_if_mapped = True;
      unixname++;
      while (*unixname && isspace(*unixname))
        unixname++;
    }
    
    if (!*unixname || strchr("#;",*unixname))
      continue;

    {
      int l = strlen(unixname);
      while (l && isspace(unixname[l-1])) {
        unixname[l-1] = 0;
        l--;
      }
    }

    if (strchr(dosname,'*') || user_in_list(user,dosname)) {
      DEBUG(3,("Mapped user %s to %s\n",user,unixname));
      mapped_user = True;
      fstrcpy(last_from,user);
      sscanf(unixname,"%s",user);
      fstrcpy(last_to,user);
      if(return_if_mapped) { 
        fclose(f);
        return True;
      }
    }
  }

  fclose(f);

  /*
   * Setup the last_from and last_to as an optimization so 
   * that we don't scan the file again for the same user.
   */
  fstrcpy(last_from,user);
  fstrcpy(last_to,user);

  return mapped_user;
}
Пример #24
0
/* list all domain groups */
static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
				TALLOC_CTX *mem_ctx,
				uint32 *num_entries, 
				struct wb_acct_info **info)
{
	ADS_STRUCT *ads = NULL;
	const char *attrs[] = {"userPrincipalName", "sAMAccountName",
			       "name", "objectSid", NULL};
	int i, count;
	ADS_STATUS rc;
	LDAPMessage *res = NULL;
	LDAPMessage *msg = NULL;
	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
	const char *filter;
	bool enum_dom_local_groups = False;

	*num_entries = 0;

	DEBUG(3,("ads: enum_dom_groups\n"));

	if ( !winbindd_can_contact_domain( domain ) ) {
		DEBUG(10,("enum_dom_groups: No incoming trust for domain %s\n",
			  domain->name));		
		return NT_STATUS_OK;
	}

	/* only grab domain local groups for our domain */
	if ( domain->active_directory && strequal(lp_realm(), domain->alt_name)  ) {
		enum_dom_local_groups = True;
	}

	/* Workaround ADS LDAP bug present in MS W2K3 SP0 and W2K SP4 w/o
	 * rollup-fixes:
	 *
	 * According to Section 5.1(4) of RFC 2251 if a value of a type is it's
	 * default value, it MUST be absent. In case of extensible matching the
	 * "dnattr" boolean defaults to FALSE and so it must be only be present
	 * when set to TRUE. 
	 *
	 * When it is set to FALSE and the OpenLDAP lib (correctly) encodes a
	 * filter using bitwise matching rule then the buggy AD fails to decode
	 * the extensible match. As a workaround set it to TRUE and thereby add
	 * the dnAttributes "dn" field to cope with those older AD versions.
	 * It should not harm and won't put any additional load on the AD since
	 * none of the dn components have a bitmask-attribute.
	 *
	 * Thanks to Ralf Haferkamp for input and testing - Guenther */

	filter = talloc_asprintf(mem_ctx, "(&(objectCategory=group)(&(groupType:dn:%s:=%d)(!(groupType:dn:%s:=%d))))", 
				 ADS_LDAP_MATCHING_RULE_BIT_AND, GROUP_TYPE_SECURITY_ENABLED,
				 ADS_LDAP_MATCHING_RULE_BIT_AND, 
				 enum_dom_local_groups ? GROUP_TYPE_BUILTIN_LOCAL_GROUP : GROUP_TYPE_RESOURCE_GROUP);

	if (filter == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	ads = ads_cached_connection(domain);

	if (!ads) {
		domain->last_status = NT_STATUS_SERVER_DISABLED;
		goto done;
	}

	rc = ads_search_retry(ads, &res, filter, attrs);
	if (!ADS_ERR_OK(rc) || !res) {
		DEBUG(1,("enum_dom_groups ads_search: %s\n", ads_errstr(rc)));
		goto done;
	}

	count = ads_count_replies(ads, res);
	if (count == 0) {
		DEBUG(1,("enum_dom_groups: No groups found\n"));
		goto done;
	}

	(*info) = talloc_zero_array(mem_ctx, struct wb_acct_info, count);
	if (!*info) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	i = 0;

	for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
		char *name, *gecos;
		struct dom_sid sid;
		uint32 rid;

		name = ads_pull_username(ads, mem_ctx, msg);
		gecos = ads_pull_string(ads, mem_ctx, msg, "name");
		if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {
			DEBUG(1,("No sid for %s !?\n", name));
			continue;
		}

		if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) {
			DEBUG(1,("No rid for %s !?\n", name));
			continue;
		}

		fstrcpy((*info)[i].acct_name, name);
		fstrcpy((*info)[i].acct_desc, gecos);
		(*info)[i].rid = rid;
		i++;
	}

	(*num_entries) = i;

	status = NT_STATUS_OK;

	DEBUG(3,("ads enum_dom_groups gave %d entries\n", (*num_entries)));

done:
	if (res) 
		ads_msgfree(ads, res);

	return status;
}
Пример #25
0
/****************************************************************************
check for authority to login to a service with a given username/password
****************************************************************************/
BOOL authorise_login(int snum,char *user,char *password, int pwlen, 
		     BOOL *guest,BOOL *force,uint16 vuid)
{
  BOOL ok = False;
  
  *guest = False;
  
#if DEBUG_PASSWORD
  DEBUG(100,("checking authorisation on user=%s pass=%s\n",user,password));
#endif

  /* there are several possibilities:
     1) login as the given user with given password
     2) login as a previously registered username with the given password
     3) login as a session list username with the given password
     4) login as a previously validated user/password pair
     5) login as the "user ="******"user ="******"ACCEPTED: given username password ok\n"));
      }

      /* check for a previously registered guest username */
      if (!ok && (vuser != 0) && vuser->guest) {	  
	if (user_ok(vuser->name,snum) &&
	    password_ok(vuser->name, password, pwlen, NULL)) {
	  pstrcpy(user, vuser->name);
	  vuser->guest = False;
	  DEBUG(3,("ACCEPTED: given password with registered user %s\n", user));
	  ok = True;
	}
      }


      /* now check the list of session users */
      if (!ok)
	{
	  char *auser;
	  char *user_list = strdup(session_users);
	  if (!user_list) return(False);

	  for (auser=strtok(user_list,LIST_SEP); 
	       !ok && auser; 
	       auser = strtok(NULL,LIST_SEP))
	    {
	      fstring user2;
	      fstrcpy(user2,auser);
	      if (!user_ok(user2,snum)) continue;
		  
	      if (password_ok(user2,password, pwlen, NULL)) {
		ok = True;
		pstrcpy(user,user2);
		DEBUG(3,("ACCEPTED: session list username and given password ok\n"));
	      }
	    }
	  free(user_list);
	}

      /* check for a previously validated username/password pair */
      if (!ok && (!lp_revalidate(snum) || lp_security() > SEC_SHARE) &&
	  (vuser != 0) && !vuser->guest &&
	  user_ok(vuser->name,snum)) {
	pstrcpy(user,vuser->name);
	*guest = False;
	DEBUG(3,("ACCEPTED: validated uid ok as non-guest\n"));
	ok = True;
      }

      /* check for a rhosts entry */
      if (!ok && user_ok(user,snum) && check_hosts_equiv(user)) {
	ok = True;
	DEBUG(3,("ACCEPTED: hosts equiv or rhosts entry\n"));
      }

      /* check the user= fields and the given password */
      if (!ok && lp_username(snum)) {
	char *auser;
	pstring user_list;
	StrnCpy(user_list,lp_username(snum),sizeof(pstring));

	string_sub(user_list,"%S",lp_servicename(snum));
	  
	for (auser=strtok(user_list,LIST_SEP);
	     auser && !ok;
	     auser = strtok(NULL,LIST_SEP))
	  {
	    if (*auser == '@')
	      {
		auser = validate_group(auser+1,password,pwlen,snum);
		if (auser)
		  {
		    ok = True;
		    pstrcpy(user,auser);
		    DEBUG(3,("ACCEPTED: group username and given password ok\n"));
		  }
	      }
	    else
	      {
		fstring user2;
		fstrcpy(user2,auser);
		if (user_ok(user2,snum) && 
		    password_ok(user2,password,pwlen,NULL))
		  {
		    ok = True;
		    pstrcpy(user,user2);
		    DEBUG(3,("ACCEPTED: user list username and given password ok\n"));
		  }
	      }
	  }
      }      
    } /* not guest only */

  /* check for a normal guest connection */
  if (!ok && GUEST_OK(snum))
    {
      fstring guestname;
      StrnCpy(guestname,lp_guestaccount(snum),sizeof(guestname)-1);
      if (Get_Pwnam(guestname,True))
	{
	  pstrcpy(user,guestname);
	  ok = True;
	  DEBUG(3,("ACCEPTED: guest account and guest ok\n"));
	}
      else
	DEBUG(0,("Invalid guest account %s??\n",guestname));
      *guest = True;
      *force = True;
    }

  if (ok && !user_ok(user,snum))
    {
      DEBUG(0,("rejected invalid user %s\n",user));
      ok = False;
    }

  return(ok);
}
Пример #26
0
static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods,
					  struct samu *sam_pass)
{
	NTSTATUS        nt_status = NT_STATUS_UNSUCCESSFUL;
	fstring 	keystr;
	uint32_t	rid;
	fstring		name;

	/* open the database */

	if ( !tdbsam_open( tdbsam_filename ) ) {
		DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n",
			 tdbsam_filename));
		return NT_STATUS_ACCESS_DENIED;
	}

	fstrcpy(name, pdb_get_username(sam_pass));
	if (!strlower_m(name)) {
		return NT_STATUS_INVALID_PARAMETER;
	}

  	/* set the search key */

	fstr_sprintf(keystr, "%s%s", USERPREFIX, name);

	rid = pdb_get_user_rid(sam_pass);

	/* it's outaa here!  8^) */

	if (dbwrap_transaction_start(db_sam) != 0) {
		DEBUG(0, ("Could not start transaction\n"));
		return NT_STATUS_UNSUCCESSFUL;
	}

	nt_status = dbwrap_delete_bystring(db_sam, keystr);
	if (!NT_STATUS_IS_OK(nt_status)) {
		DEBUG(5, ("Error deleting entry from tdb passwd "
			  "database: %s!\n", nt_errstr(nt_status)));
		goto cancel;
	}

  	/* set the search key */

	fstr_sprintf(keystr, "%s%.8x", RIDPREFIX, rid);

	/* it's outaa here!  8^) */

	nt_status = dbwrap_delete_bystring(db_sam, keystr);
	if (!NT_STATUS_IS_OK(nt_status)) {
		DEBUG(5, ("Error deleting entry from tdb rid "
			  "database: %s!\n", nt_errstr(nt_status)));
		goto cancel;
	}

	if (dbwrap_transaction_commit(db_sam) != 0) {
		DEBUG(0, ("Could not commit transaction\n"));
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	return NT_STATUS_OK;

 cancel:
	if (dbwrap_transaction_cancel(db_sam) != 0) {
		smb_panic("transaction_cancel failed");
	}

	return nt_status;
}
Пример #27
0
/****************************************************************************
support for server level security 
****************************************************************************/
struct cli_state *server_cryptkey(void)
{
	fstring desthost;
	struct in_addr dest_ip;
	extern fstring local_machine;
	char *p;

	if (!cli_initialise(&cli))
		return NULL;
	    
	for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) {
		fstrcpy(desthost,p);
		standard_sub_basic(desthost);
		strupper(desthost);

                if(!resolve_name( desthost, &dest_ip)) {
			DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",p));
			continue;
		}

		if (ismyip(dest_ip)) {
			DEBUG(1,("Password server loop - disabling password server %s\n",p));
			continue;
		}

		if (cli_connect(&cli, desthost, &dest_ip)) {
			DEBUG(3,("connected to password server %s\n",p));
			break;
		}
	}

	if (!p) {
		DEBUG(1,("password server not available\n"));
		cli_shutdown(&cli);
		return NULL;
	}

	if (!cli_session_request(&cli, desthost, 0x20, local_machine)) {
		DEBUG(1,("%s rejected the session\n",desthost));
		cli_shutdown(&cli);
		return NULL;
	}

	DEBUG(3,("got session\n"));

	if (!cli_negprot(&cli)) {
		DEBUG(1,("%s rejected the negprot\n",desthost));
		cli_shutdown(&cli);
		return NULL;
	}

	if (cli.protocol < PROTOCOL_LANMAN2 ||
	    !(cli.sec_mode & 1)) {
		DEBUG(1,("%s isn't in user level security mode\n",desthost));
		cli_shutdown(&cli);
		return NULL;
	}

	DEBUG(3,("password server OK\n"));

	return &cli;
}
Пример #28
0
/***************************************************************************
 Renames a struct samu
 - check for the posix user/rename user script
 - Add and lock the new user record
 - rename the posix user
 - rewrite the rid->username record
 - delete the old user
 - unlock the new user record
***************************************************************************/
static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
					  struct samu *old_acct,
					  const char *newname)
{
	struct samu      *new_acct = NULL;
	char *rename_script = NULL;
	int              rename_ret;
	fstring          oldname_lower;
	fstring          newname_lower;

	/* can't do anything without an external script */

	if ( !(new_acct = samu_new( talloc_tos() )) ) {
		return NT_STATUS_NO_MEMORY;
	}

	rename_script = lp_rename_user_script(new_acct);
	if (!rename_script) {
		TALLOC_FREE(new_acct);
		return NT_STATUS_NO_MEMORY;
	}
	if (!*rename_script) {
		TALLOC_FREE(new_acct);
		return NT_STATUS_ACCESS_DENIED;
	}

	if ( !pdb_copy_sam_account(new_acct, old_acct)
		|| !pdb_set_username(new_acct, newname, PDB_CHANGED))
	{
		TALLOC_FREE(new_acct);
		return NT_STATUS_NO_MEMORY;
	}

	/* open the database */
	if ( !tdbsam_open( tdbsam_filename ) ) {
		DEBUG(0, ("tdbsam_getsampwnam: failed to open %s!\n",
			  tdbsam_filename));
		TALLOC_FREE(new_acct);
		return NT_STATUS_ACCESS_DENIED;
	}

	if (dbwrap_transaction_start(db_sam) != 0) {
		DEBUG(0, ("Could not start transaction\n"));
		TALLOC_FREE(new_acct);
		return NT_STATUS_ACCESS_DENIED;

	}

	/* add the new account and lock it */
	if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) ) {
		goto cancel;
	}

	/* Rename the posix user.  Follow the semantics of _samr_create_user()
	   so that we lower case the posix name but preserve the case in passdb */

	fstrcpy( oldname_lower, pdb_get_username(old_acct) );
	if (!strlower_m( oldname_lower )) {
		goto cancel;
	}

	fstrcpy( newname_lower, newname );
	if (!strlower_m( newname_lower )) {
		goto cancel;
	}

	rename_script = talloc_string_sub2(new_acct,
				rename_script,
				"%unew",
				newname_lower,
				true,
				false,
				true);
	if (!rename_script) {
		goto cancel;
	}
	rename_script = talloc_string_sub2(new_acct,
				rename_script,
				"%uold",
				oldname_lower,
				true,
				false,
				true);
	if (!rename_script) {
		goto cancel;
	}
	rename_ret = smbrun(rename_script, NULL, NULL);

	DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n",
				rename_script, rename_ret));

	if (rename_ret != 0) {
		goto cancel;
	}

	smb_nscd_flush_user_cache();

	/* rewrite the rid->username record */

	if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) ) {
		goto cancel;
	}

	tdb_delete_samacct_only( old_acct );

	if (dbwrap_transaction_commit(db_sam) != 0) {
		/*
		 * Ok, we're screwed. We've changed the posix account, but
		 * could not adapt passdb.tdb. Shall we change the posix
		 * account back?
		 */
		DEBUG(0, ("transaction_commit failed\n"));
		TALLOC_FREE(new_acct);
		return NT_STATUS_INTERNAL_DB_CORRUPTION;	
	}

	TALLOC_FREE(new_acct );
	return NT_STATUS_OK;

 cancel:
	if (dbwrap_transaction_cancel(db_sam) != 0) {
		smb_panic("transaction_cancel failed");
	}

	TALLOC_FREE(new_acct);

	return NT_STATUS_ACCESS_DENIED;	
}
Пример #29
0
static void
inquire_via_unit (st_parameter_inquire *iqp, gfc_unit * u)
{
  const char *p;
  GFC_INTEGER_4 cf = iqp->common.flags;

  if (iqp->common.unit == GFC_INTERNAL_UNIT ||
	iqp->common.unit == GFC_INTERNAL_UNIT4 ||
	u->internal_unit_kind != 0)
    generate_error (&iqp->common, LIBERROR_INQUIRE_INTERNAL_UNIT, NULL);

  if ((cf & IOPARM_INQUIRE_HAS_EXIST) != 0)
    *iqp->exist = (u != NULL) || (iqp->common.unit >= 0);

  if ((cf & IOPARM_INQUIRE_HAS_OPENED) != 0)
    *iqp->opened = (u != NULL);

  if ((cf & IOPARM_INQUIRE_HAS_NUMBER) != 0)
    *iqp->number = (u != NULL) ? u->unit_number : -1;

  if ((cf & IOPARM_INQUIRE_HAS_NAMED) != 0)
    *iqp->named = (u != NULL && u->flags.status != STATUS_SCRATCH);

  if ((cf & IOPARM_INQUIRE_HAS_NAME) != 0
      && u != NULL && u->flags.status != STATUS_SCRATCH)
    {
#if defined(HAVE_TTYNAME_R) || defined(HAVE_TTYNAME)
      if (u->unit_number == options.stdin_unit
	  || u->unit_number == options.stdout_unit
	  || u->unit_number == options.stderr_unit)
	{
	  int err = stream_ttyname (u->s, iqp->name, iqp->name_len);
	  if (err == 0)
	    {
	      gfc_charlen_type tmplen = strlen (iqp->name);
	      if (iqp->name_len > tmplen)
		memset (&iqp->name[tmplen], ' ', iqp->name_len - tmplen);
	    }
	  else /* If ttyname does not work, go with the default.  */
	    cf_strcpy (iqp->name, iqp->name_len, u->filename);
	}
      else
	cf_strcpy (iqp->name, iqp->name_len, u->filename);
#elif defined __MINGW32__
      if (u->unit_number == options.stdin_unit)
	fstrcpy (iqp->name, iqp->name_len, "CONIN$", sizeof("CONIN$"));
      else if (u->unit_number == options.stdout_unit)
	fstrcpy (iqp->name, iqp->name_len, "CONOUT$", sizeof("CONOUT$"));
      else if (u->unit_number == options.stderr_unit)
	fstrcpy (iqp->name, iqp->name_len, "CONERR$", sizeof("CONERR$"));
      else
	cf_strcpy (iqp->name, iqp->name_len, u->filename);
#else
      cf_strcpy (iqp->name, iqp->name_len, u->filename);
#endif
    }

  if ((cf & IOPARM_INQUIRE_HAS_ACCESS) != 0)
    {
      if (u == NULL)
	p = undefined;
      else
	switch (u->flags.access)
	  {
	  case ACCESS_SEQUENTIAL:
	    p = "SEQUENTIAL";
	    break;
	  case ACCESS_DIRECT:
	    p = "DIRECT";
	    break;
	  case ACCESS_STREAM:
	    p = "STREAM";
	    break;
	  default:
	    internal_error (&iqp->common, "inquire_via_unit(): Bad access");
	  }

      cf_strcpy (iqp->access, iqp->access_len, p);
    }

  if ((cf & IOPARM_INQUIRE_HAS_SEQUENTIAL) != 0)
    {
      if (u == NULL)
	p = inquire_sequential (NULL, 0);
      else
	switch (u->flags.access)
	  {
	  case ACCESS_DIRECT:
	  case ACCESS_STREAM:
	    p = no;
	    break;
	  case ACCESS_SEQUENTIAL:
	    p = yes;
	    break;
	  default:
	    internal_error (&iqp->common, "inquire_via_unit(): Bad access");
	  }

      cf_strcpy (iqp->sequential, iqp->sequential_len, p);
    }

  if ((cf & IOPARM_INQUIRE_HAS_DIRECT) != 0)
    {
      if (u == NULL)
	p = inquire_direct (NULL, 0);
      else
	switch (u->flags.access)
	  {
	  case ACCESS_SEQUENTIAL:
	  case ACCESS_STREAM:
	    p = no;
	    break;
	  case ACCESS_DIRECT:
	    p = yes;
	    break;
	  default:
	    internal_error (&iqp->common, "inquire_via_unit(): Bad access");
	  }

      cf_strcpy (iqp->direct, iqp->direct_len, p);
    }

  if ((cf & IOPARM_INQUIRE_HAS_FORM) != 0)
    {
      if (u == NULL)
	p = undefined;
      else
	switch (u->flags.form)
	  {
	  case FORM_FORMATTED:
	    p = "FORMATTED";
	    break;
	  case FORM_UNFORMATTED:
	    p = "UNFORMATTED";
	    break;
	  default:
	    internal_error (&iqp->common, "inquire_via_unit(): Bad form");
	  }

      cf_strcpy (iqp->form, iqp->form_len, p);
    }

  if ((cf & IOPARM_INQUIRE_HAS_FORMATTED) != 0)
    {
      if (u == NULL)
	p = inquire_formatted (NULL, 0);
      else
	switch (u->flags.form)
	  {
	  case FORM_FORMATTED:
	    p = yes;
	    break;
	  case FORM_UNFORMATTED:
	    p = no;
	    break;
	  default:
	    internal_error (&iqp->common, "inquire_via_unit(): Bad form");
	  }

      cf_strcpy (iqp->formatted, iqp->formatted_len, p);
    }

  if ((cf & IOPARM_INQUIRE_HAS_UNFORMATTED) != 0)
    {
      if (u == NULL)
	p = inquire_unformatted (NULL, 0);
      else
	switch (u->flags.form)
	  {
	  case FORM_FORMATTED:
	    p = no;
	    break;
	  case FORM_UNFORMATTED:
	    p = yes;
	    break;
	  default:
	    internal_error (&iqp->common, "inquire_via_unit(): Bad form");
	  }

      cf_strcpy (iqp->unformatted, iqp->unformatted_len, p);
    }

  if ((cf & IOPARM_INQUIRE_HAS_RECL_OUT) != 0)
    *iqp->recl_out = (u != NULL) ? u->recl : 0;

  if ((cf & IOPARM_INQUIRE_HAS_STRM_POS_OUT) != 0)
    *iqp->strm_pos_out = (u != NULL) ? u->strm_pos : 0;

  if ((cf & IOPARM_INQUIRE_HAS_NEXTREC) != 0)
    {
      /* This only makes sense in the context of DIRECT access.  */
      if (u != NULL && u->flags.access == ACCESS_DIRECT)
	*iqp->nextrec = u->last_record + 1;
      else
	*iqp->nextrec = 0;
    }

  if ((cf & IOPARM_INQUIRE_HAS_BLANK) != 0)
    {
      if (u == NULL || u->flags.form != FORM_FORMATTED)
	p = undefined;
      else
	switch (u->flags.blank)
	  {
	  case BLANK_NULL:
	    p = "NULL";
	    break;
	  case BLANK_ZERO:
	    p = "ZERO";
	    break;
	  default:
	    internal_error (&iqp->common, "inquire_via_unit(): Bad blank");
	  }

      cf_strcpy (iqp->blank, iqp->blank_len, p);
    }

  if ((cf & IOPARM_INQUIRE_HAS_PAD) != 0)
    {
      if (u == NULL || u->flags.form != FORM_FORMATTED)
	p = undefined;
      else
	switch (u->flags.pad)
	  {
	  case PAD_YES:
	    p = yes;
	    break;
	  case PAD_NO:
	    p = no;
	    break;
	  default:
	    internal_error (&iqp->common, "inquire_via_unit(): Bad pad");
	  }

      cf_strcpy (iqp->pad, iqp->pad_len, p);
    }

  if (cf & IOPARM_INQUIRE_HAS_FLAGS2)
    {
      GFC_INTEGER_4 cf2 = iqp->flags2;

      if ((cf2 & IOPARM_INQUIRE_HAS_PENDING) != 0)
	*iqp->pending = 0;
  
      if ((cf2 & IOPARM_INQUIRE_HAS_ID) != 0)
        *iqp->id = 0;

      if ((cf2 & IOPARM_INQUIRE_HAS_ENCODING) != 0)
	{
	  if (u == NULL || u->flags.form != FORM_FORMATTED)
	    p = undefined;
          else
	    switch (u->flags.encoding)
	      {
	      case ENCODING_DEFAULT:
		p = "UNKNOWN";
		break;
	      case ENCODING_UTF8:
		p = "UTF-8";
		break;
	      default:
		internal_error (&iqp->common, "inquire_via_unit(): Bad encoding");
	      }

	  cf_strcpy (iqp->encoding, iqp->encoding_len, p);
	}

      if ((cf2 & IOPARM_INQUIRE_HAS_DECIMAL) != 0)
	{
	  if (u == NULL || u->flags.form != FORM_FORMATTED)
	    p = undefined;
	  else
	    switch (u->flags.decimal)
	      {
	      case DECIMAL_POINT:
		p = "POINT";
		break;
	      case DECIMAL_COMMA:
		p = "COMMA";
		break;
	      default:
		internal_error (&iqp->common, "inquire_via_unit(): Bad comma");
	      }

	  cf_strcpy (iqp->decimal, iqp->decimal_len, p);
	}

      if ((cf2 & IOPARM_INQUIRE_HAS_ASYNCHRONOUS) != 0)
	{
	  if (u == NULL)
	    p = undefined;
	  else
	    switch (u->flags.async)
	    {
	      case ASYNC_YES:
		p = yes;
		break;
	      case ASYNC_NO:
		p = no;
		break;
	      default:
		internal_error (&iqp->common, "inquire_via_unit(): Bad async");
	    }

	  cf_strcpy (iqp->asynchronous, iqp->asynchronous_len, p);
	}

      if ((cf2 & IOPARM_INQUIRE_HAS_SIGN) != 0)
	{
	  if (u == NULL)
	    p = undefined;
	  else
	    switch (u->flags.sign)
	    {
	      case SIGN_PROCDEFINED:
		p = "PROCESSOR_DEFINED";
		break;
	      case SIGN_SUPPRESS:
		p = "SUPPRESS";
		break;
	      case SIGN_PLUS:
		p = "PLUS";
		break;
	      default:
		internal_error (&iqp->common, "inquire_via_unit(): Bad sign");
	    }

	  cf_strcpy (iqp->sign, iqp->sign_len, p);
	}

      if ((cf2 & IOPARM_INQUIRE_HAS_ROUND) != 0)
	{
	  if (u == NULL)
	    p = undefined;
	  else
	    switch (u->flags.round)
	    {
	      case ROUND_UP:
		p = "UP";
		break;
	      case ROUND_DOWN:
		p = "DOWN";
		break;
	      case ROUND_ZERO:
		p = "ZERO";
		break;
	      case ROUND_NEAREST:
		p = "NEAREST";
		break;
	      case ROUND_COMPATIBLE:
		p = "COMPATIBLE";
		break;
	      case ROUND_PROCDEFINED:
		p = "PROCESSOR_DEFINED";
		break;
	      default:
		internal_error (&iqp->common, "inquire_via_unit(): Bad round");
	    }

	  cf_strcpy (iqp->round, iqp->round_len, p);
	}

      if ((cf2 & IOPARM_INQUIRE_HAS_SIZE) != 0)
	{
	  if (u == NULL)
	    *iqp->size = -1;
	  else
	    {
	      sflush (u->s);
	      *iqp->size = ssize (u->s);
	    }
	}

      if ((cf2 & IOPARM_INQUIRE_HAS_IQSTREAM) != 0)
	{
	  if (u == NULL)
	    p = "UNKNOWN";
	  else
	    switch (u->flags.access)
	      {
	      case ACCESS_SEQUENTIAL:
	      case ACCESS_DIRECT:
		p = no;
		break;
	      case ACCESS_STREAM:
		p = yes;
		break;
	      default:
		internal_error (&iqp->common, "inquire_via_unit(): Bad pad");
	      }
    
	  cf_strcpy (iqp->iqstream, iqp->iqstream_len, p);
	}
    }

  if ((cf & IOPARM_INQUIRE_HAS_POSITION) != 0)
    {
      if (u == NULL || u->flags.access == ACCESS_DIRECT)
        p = undefined;
      else
	{
	  /* If the position is unspecified, check if we can figure
	     out whether it's at the beginning or end.  */
	  if (u->flags.position == POSITION_UNSPECIFIED)
	    {
	      gfc_offset cur = stell (u->s);
	      if (cur == 0)
		u->flags.position = POSITION_REWIND;
	      else if (cur != -1 && (ssize (u->s) == cur))
		u->flags.position = POSITION_APPEND;
	    }
	  switch (u->flags.position)
	    {
	    case POSITION_REWIND:
	      p = "REWIND";
	      break;
	    case POSITION_APPEND:
	      p = "APPEND";
	      break;
	    case POSITION_ASIS:
	      p = "ASIS";
	      break;
	    default:
	      /* If the position has changed and is not rewind or
		 append, it must be set to a processor-dependent
		 value.  */
	      p = "UNSPECIFIED";
	      break;
	    }
	}
      cf_strcpy (iqp->position, iqp->position_len, p);
    }

  if ((cf & IOPARM_INQUIRE_HAS_ACTION) != 0)
    {
      if (u == NULL)
	p = undefined;
      else
	switch (u->flags.action)
	  {
	  case ACTION_READ:
	    p = "READ";
	    break;
	  case ACTION_WRITE:
	    p = "WRITE";
	    break;
	  case ACTION_READWRITE:
	    p = "READWRITE";
	    break;
	  default:
	    internal_error (&iqp->common, "inquire_via_unit(): Bad action");
	  }

      cf_strcpy (iqp->action, iqp->action_len, p);
    }

  if ((cf & IOPARM_INQUIRE_HAS_READ) != 0)
    {
      p = (!u || u->flags.action == ACTION_WRITE) ? no : yes;
      cf_strcpy (iqp->read, iqp->read_len, p);
    }

  if ((cf & IOPARM_INQUIRE_HAS_WRITE) != 0)
    {
      p = (!u || u->flags.action == ACTION_READ) ? no : yes;
      cf_strcpy (iqp->write, iqp->write_len, p);
    }

  if ((cf & IOPARM_INQUIRE_HAS_READWRITE) != 0)
    {
      p = (!u || u->flags.action != ACTION_READWRITE) ? no : yes;
      cf_strcpy (iqp->readwrite, iqp->readwrite_len, p);
    }

  if ((cf & IOPARM_INQUIRE_HAS_DELIM) != 0)
    {
      if (u == NULL || u->flags.form != FORM_FORMATTED)
	p = undefined;
      else
	switch (u->flags.delim)
	  {
	  case DELIM_NONE:
	  case DELIM_UNSPECIFIED:
	    p = "NONE";
	    break;
	  case DELIM_QUOTE:
	    p = "QUOTE";
	    break;
	  case DELIM_APOSTROPHE:
	    p = "APOSTROPHE";
	    break;
	  default:
	    internal_error (&iqp->common, "inquire_via_unit(): Bad delim");
	  }

      cf_strcpy (iqp->delim, iqp->delim_len, p);
    }

  if ((cf & IOPARM_INQUIRE_HAS_PAD) != 0)
    {
      if (u == NULL || u->flags.form != FORM_FORMATTED)
	p = undefined;
      else
	switch (u->flags.pad)
	  {
	  case PAD_NO:
	    p = no;
	    break;
	  case PAD_YES:
	    p = yes;
	    break;
	  default:
	    internal_error (&iqp->common, "inquire_via_unit(): Bad pad");
	  }

      cf_strcpy (iqp->pad, iqp->pad_len, p);
    }
 
  if ((cf & IOPARM_INQUIRE_HAS_CONVERT) != 0)
    {
      if (u == NULL)
	p = undefined;
      else
	switch (u->flags.convert)
	  {
	    /*  big_endian is 0 for little-endian, 1 for big-endian.  */
	  case GFC_CONVERT_NATIVE:
	    p = big_endian ? "BIG_ENDIAN" : "LITTLE_ENDIAN";
	    break;

	  case GFC_CONVERT_SWAP:
	    p = big_endian ? "LITTLE_ENDIAN" : "BIG_ENDIAN";
	    break;

	  default:
	    internal_error (&iqp->common, "inquire_via_unit(): Bad convert");
	  }

      cf_strcpy (iqp->convert, iqp->convert_len, p);
    }
}
Пример #30
0
static int driver_arch_fetch_values( char *key, REGVAL_CTR *values )
{
	char 		*keystr, *base, *subkeypath;
	fstring		arch_environment;
	fstring		driver;
	int		version;
	NT_PRINTER_DRIVER_INFO_LEVEL	driver_ctr;
	WERROR		w_result;

	if (!reg_split_path( key, &base, &subkeypath )) {
		return -1;
	}
	
	/* no values in 'Environments\Drivers\Windows NT x86' */
	
	if ( !subkeypath ) 
		return 0;
		
	/* We have the Architecture string and some subkey name:
	   Currently we only support
	   * Drivers
	   * Print Processors
	   Anything else is an error.
	   */

	fstrcpy( arch_environment, base );
	
	keystr = subkeypath;
	if (!reg_split_path( keystr, &base, &subkeypath )) {
		return -1;
	}

	if ( strequal(base, "Print Processors") )
		return 0;

	/* only Drivers key can be left */
		
	if ( !strequal(base, "Drivers") )
		return -1;
			
	if ( !subkeypath )
		return 0;
	
	/* We know that we have Architechure\Drivers with some subkey name
	   The subkey name has to be Version-XX */
	
	keystr = subkeypath;
	if (!reg_split_path( keystr, &base, &subkeypath )) {
		return -1;
	}

	if ( !subkeypath )
		return 0;
		
	version = atoi(&base[strlen(base)-1]);

	/* BEGIN PRINTER DRIVER NAME BLOCK */
	
	keystr = subkeypath;
	if (!reg_split_path( keystr, &base, &subkeypath )) {
		return -1;
	}
	
	/* don't go any deeper for now */
	
	fstrcpy( driver, base );
	
	w_result = get_a_printer_driver( &driver_ctr, 3, driver, arch_environment, version );

	if ( !W_ERROR_IS_OK(w_result) )
		return -1;
		
	fill_in_driver_values( driver_ctr.info_3, values ); 
	
	free_a_printer_driver( driver_ctr, 3 );

	/* END PRINTER DRIVER NAME BLOCK */

						
	DEBUG(8,("key_driver_fetch_values: Exit\n"));
	
	return regval_ctr_numvals( values );
}