Example #1
0
/* return true if access should be allowed to a service*/
BOOL check_access(int snum)
{
  char *denyl,*allowl;
  BOOL ret = False;

  denyl = lp_hostsdeny(snum);
  if (denyl) denyl = strdup(denyl);

  allowl = lp_hostsallow(snum);
  if (allowl) allowl = strdup(allowl);

  if ((!denyl || *denyl==0) && (!allowl || *allowl==0))
    ret = True;

  if (!ret)
    {
      if (allow_access(denyl,allowl,client_name(),client_addr()))
	{
	  if (snum >= 0)
	    DEBUG(2,("Allowed connection from %s (%s) to %s\n",
		     client_name(),client_addr(),
		     lp_servicename(snum)));
	  ret = True;
	}
      else
	if (snum >= 0)
	  DEBUG(0,("%s Denied connection from %s (%s) to %s\n",
		   timestring(), client_name(),client_addr(),
		   lp_servicename(snum)));
    }

  if (denyl) free(denyl);
  if (allowl) free(allowl);
  return(ret);
}
Example #2
0
/**
 * Return the DNS name of the client.
 *
 * The name is statically cached so that repeated lookups are quick,
 * so there is a limit of one lookup per customer.
 *
 * If anything goes wrong, including the name->addr->name check, then
 * we just use "UNKNOWN", so you can use that value in hosts allow
 * lines.
 *
 * After translation from sockaddr to name we do a forward lookup to
 * make sure nobody is spoofing PTR records.
 **/
char *client_name(int fd)
{
	static char name_buf[100];
	static char port_buf[100];
	static int initialised;
	struct sockaddr_storage ss;
	socklen_t ss_len;

	if (initialised)
		return name_buf;

	strlcpy(name_buf, default_name, sizeof name_buf);
	initialised = 1;

	memset(&ss, 0, sizeof ss);

	if (am_server) {	/* daemon over --rsh mode */
		char *addr = client_addr(fd);
		struct addrinfo hint, *answer;
		int err;

		memset(&hint, 0, sizeof hint);

#ifdef AI_NUMERICHOST
		hint.ai_flags = AI_NUMERICHOST;
#endif
		hint.ai_socktype = SOCK_STREAM;

		if ((err = getaddrinfo(addr, NULL, &hint, &answer)) != 0) {
			rprintf(FLOG, "malformed address %s: %s\n",
			        addr, gai_strerror(err));
			return name_buf;
		}

		switch (answer->ai_family) {
		case AF_INET:
			ss_len = sizeof (struct sockaddr_in);
			memcpy(&ss, answer->ai_addr, ss_len);
			break;
#ifdef INET6
		case AF_INET6:
			ss_len = sizeof (struct sockaddr_in6);
			memcpy(&ss, answer->ai_addr, ss_len);
			break;
#endif
		default:
			exit_cleanup(RERR_SOCKETIO);
		}
		freeaddrinfo(answer);
	} else {
		ss_len = sizeof ss;
		client_sockaddr(fd, &ss, &ss_len);
	}

	if (lookup_name(fd, &ss, ss_len, name_buf, sizeof name_buf,
			port_buf, sizeof port_buf) == 0)
		check_name(fd, &ss, name_buf, sizeof name_buf);

	return name_buf;
}
        void hpc_network_provider::do_accept()
        {
            while (true)
            {
                struct sockaddr_in addr;
                socklen_t addr_len = (socklen_t)sizeof(addr);
                socket_t s = ::accept(_listen_fd, (struct sockaddr*)&addr, &addr_len);
                if (s != -1)
                {
                    ::dsn::rpc_address client_addr(ntohl(addr.sin_addr.s_addr), ntohs(addr.sin_port));

                    auto parser = new_message_parser();
                    auto rs = new hpc_rpc_session(s, parser, *this, client_addr);
                    rpc_session_ptr s1(rs);

                    rs->bind_looper(_looper);
                    this->on_server_session_accepted(s1);
                }
                else
                {
                    if (errno != EAGAIN && errno != EWOULDBLOCK)
                    {
                        derror("accept failed, err = %s", strerror(errno));
                    }                    
                    break;
                }
            }
        }
Example #4
0
/*******************************************************************
 return the DNS name of the client 
 ******************************************************************/
char *
client_name (int fd)
{
    struct sockaddr sa;
    struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
    unsigned int length = sizeof (sa);
    static pstring name_buf;
    struct hostent *hp;
    static int last_fd = -1;

    if (global_client_name_done && last_fd == fd)
        return name_buf;

    last_fd = fd;
    global_client_name_done = False;

    pstrcpy (name_buf, "UNKNOWN");

    if (fd == -1)
    {
        return name_buf;
    }

    if (getpeername (fd, &sa, &length) < 0)
    {
        DEBUG (0, ("getpeername failed. Error was %s\n", unix_error_string (errno)));
        return name_buf;
    }

    /* Look up the remote host name. */
    if ((hp = gethostbyaddr ((char *) &sockin->sin_addr, sizeof (sockin->sin_addr), AF_INET)) == 0)
    {
        DEBUG (1, ("Gethostbyaddr failed for %s\n", client_addr (fd)));
        StrnCpy (name_buf, client_addr (fd), sizeof (name_buf) - 1);
    }
    else
    {
        StrnCpy (name_buf, (char *) hp->h_name, sizeof (name_buf) - 1);
        if (!matchname (name_buf, sockin->sin_addr))
        {
            DEBUG (0, ("Matchname failed on %s %s\n", name_buf, client_addr (fd)));
            pstrcpy (name_buf, "UNKNOWN");
        }
    }
    global_client_name_done = True;
    return name_buf;
}
Example #5
0
static BOOL get_md4pw(char *md4pw, char *mach_acct)
{
	SAM_ACCOUNT *sampass = NULL;
	const uint8 *pass;
	BOOL ret;
	uint32 acct_ctrl;

#if 0
    /*
     * Currently this code is redundent as we already have a filter
     * by hostname list. What this code really needs to do is to 
     * get a hosts allowed/hosts denied list from the SAM database
     * on a per user basis, and make the access decision there.
     * I will leave this code here for now as a reminder to implement
     * this at a later date. JRA.
     */

	if (!allow_access(lp_domain_hostsdeny(), lp_domain_hostsallow(),
	                  client_name(), client_addr()))
	{
		DEBUG(0,("get_md4pw: Workstation %s denied access to domain\n", mach_acct));
		return False;
	}
#endif /* 0 */

	if(!NT_STATUS_IS_OK(pdb_init_sam(&sampass)))
		return False;

	/* JRA. This is ok as it is only used for generating the challenge. */
	become_root();
	ret=pdb_getsampwnam(sampass, mach_acct);
	unbecome_root();
 
 	if (ret==False) {
 		DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
		pdb_free_sam(&sampass);
		return False;
	}

	acct_ctrl = pdb_get_acct_ctrl(sampass);
	if (!(acct_ctrl & ACB_DISABLED) &&
	    ((acct_ctrl & ACB_DOMTRUST) ||
	     (acct_ctrl & ACB_WSTRUST) ||
	     (acct_ctrl & ACB_SVRTRUST)) &&
	    ((pass=pdb_get_nt_passwd(sampass)) != NULL)) {
		memcpy(md4pw, pass, 16);
		dump_data(5, md4pw, 16);
 		pdb_free_sam(&sampass);
		return True;
	}
 	
	DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
	pdb_free_sam(&sampass);
	return False;

}
Example #6
0
/* Callback from GSSRPC for authentication failures */
void
log_badauth(OM_uint32 major, OM_uint32 minor, SVCXPRT *xprt, char *data)
{
    krb5_klog_syslog(LOG_NOTICE, _("Authentication attempt failed: %s, "
                                   "GSS-API error strings are:"),
                     client_addr(xprt));
    log_badauth_display_status_1("   ", major, GSS_C_GSS_CODE);
    log_badauth_display_status_1("   ", minor, GSS_C_MECH_CODE);
    krb5_klog_syslog(LOG_NOTICE, _("   GSS-API error strings complete."));
}
Example #7
0
static void setup_new_vc_session(void)
{
	DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
#if 0
	conn_close_all();
	invalidate_all_vuids();
#endif
	if (lp_reset_on_zero_vc()) {
		session_traverse(shutdown_other_smbds, client_addr());
	}
}
Example #8
0
static BOOL read_target_host(const char *mapfile, pstring targethost)
{
    XFILE *f;
    pstring buf;
    char *s, *space = buf;
    BOOL found = False;

    f = x_fopen(mapfile, O_RDONLY, 0);

    if (f == NULL) {
        DEBUG(0,("can't open IP map %s. Error %s\n",
                 mapfile, strerror(errno) ));
        return False;
    }

    DEBUG(10, ("Scanning mapfile [%s]\n", mapfile));

    while ((s=x_fgets(buf, sizeof(buf), f)) != NULL) {

        if ((strlen(buf) > 0) && (buf[strlen(buf)-1] == '\n'))
            buf[strlen(buf)-1] = '\0';

        DEBUG(10, ("Scanning line [%s]\n", buf));

        space = strchr_m(buf, ' ');

        if (space == NULL) {
            DEBUG(0, ("Ignoring invalid line %s\n", buf));
            continue;
        }

        *space = '\0';

        if (strncmp(client_addr(), buf, strlen(buf)) == 0) {
            found = True;
            break;
        }
    }

    x_fclose(f);

    if (!found)
        return False;

    space += 1;

    while (isspace(*space))
        space += 1;

    pstrcpy(targethost, space);
    return True;
}
Example #9
0
/**
 * Do a forward lookup on @p name_buf and make sure it corresponds to
 * @p ss -- otherwise we may be being spoofed.  If we suspect we are,
 * then we don't abort the connection but just emit a warning, and
 * change @p name_buf to be "UNKNOWN".
 *
 * We don't do anything with the service when checking the name,
 * because it doesn't seem that it could be spoofed in any way, and
 * getaddrinfo on random service names seems to cause problems on AIX.
 **/
int check_name(int fd,
	       const struct sockaddr_storage *ss,
	       char *name_buf, size_t name_buf_size)
{
	struct addrinfo hints, *res, *res0;
	int error;
	int ss_family = get_sockaddr_family(ss);

	memset(&hints, 0, sizeof hints);
	hints.ai_family = ss_family;
	hints.ai_flags = AI_CANONNAME;
	hints.ai_socktype = SOCK_STREAM;
	error = getaddrinfo(name_buf, NULL, &hints, &res0);
	if (error) {
		rprintf(FLOG, "forward name lookup for %s failed: %s\n",
			name_buf, gai_strerror(error));
		strlcpy(name_buf, default_name, name_buf_size);
		return error;
	}

	/* Given all these results, we expect that one of them will be
	 * the same as ss.  The comparison is a bit complicated. */
	for (res = res0; res; res = res->ai_next) {
		if (!compare_addrinfo_sockaddr(res, ss))
			break;	/* OK, identical */
	}

	if (!res0) {
		/* We hit the end of the list without finding an
		 * address that was the same as ss. */
		rprintf(FLOG, "no known address for \"%s\": "
			"spoofed address?\n", name_buf);
		strlcpy(name_buf, default_name, name_buf_size);
	} else if (res == NULL) {
		/* We hit the end of the list without finding an
		 * address that was the same as ss. */
		rprintf(FLOG, "%s is not a known address for \"%s\": "
			"spoofed address?\n", client_addr(fd), name_buf);
		strlcpy(name_buf, default_name, name_buf_size);
	}

	freeaddrinfo(res0);
	return 0;
}
Example #10
0
/**
 * Look up a name from @p ss into @p name_buf.
 *
 * @param fd file descriptor for client socket.
 **/
int lookup_name(int fd, const struct sockaddr_storage *ss,
		socklen_t ss_len,
		char *name_buf, size_t name_buf_size,
		char *port_buf, size_t port_buf_size)
{
	int name_err;

	/* reverse lookup */
	name_err = getnameinfo((struct sockaddr *) ss, ss_len,
			       name_buf, name_buf_size,
			       port_buf, port_buf_size,
			       NI_NAMEREQD | NI_NUMERICSERV);
	if (name_err != 0) {
		strlcpy(name_buf, default_name, name_buf_size);
		rprintf(FLOG, "name lookup failed for %s: %s\n",
			client_addr(fd), gai_strerror(name_err));
		return name_err;
	}

	return 0;
}
void hpc_network_provider::do_accept()
{
    socket_t s = create_tcp_socket(nullptr);
    dassert(s != INVALID_SOCKET, "cannot create socket for accept");

    _accept_sock = s;
    _accept_event.callback = [this](int err, uint32_t size, uintptr_t lpolp)
    {
        //dinfo("accept completed, err = %d, size = %u", err, size);
        dassert(&_accept_event.olp == (LPOVERLAPPED)lpolp, "must be this exact overlap");
        if (err == ERROR_SUCCESS)
        {
            setsockopt(_accept_sock,
                       SOL_SOCKET,
                       SO_UPDATE_ACCEPT_CONTEXT,
                       (char *)&_listen_fd,
                       sizeof(_listen_fd)
                      );

            struct sockaddr_in addr;
            memset((void*)&addr, 0, sizeof(addr));

            addr.sin_family = AF_INET;
            addr.sin_addr.s_addr = INADDR_ANY;
            addr.sin_port = 0;

            int addr_len = sizeof(addr);
            if (getpeername(_accept_sock, (struct sockaddr*)&addr, &addr_len)
                    == SOCKET_ERROR)
            {
                dassert(false, "getpeername failed, err = %d", ::WSAGetLastError());
            }

            ::dsn::rpc_address client_addr(ntohl(addr.sin_addr.s_addr), ntohs(addr.sin_port));

            auto parser = new_message_parser();
            auto s = new hpc_rpc_session(_accept_sock, parser, *this, client_addr);
            rpc_session_ptr s1(s);
            s->bind_looper(_looper);

            this->on_server_session_accepted(s1);

            s->do_read();
        }
        else
        {
            closesocket(_accept_sock);
        }

        do_accept();
    };
    memset(&_accept_event.olp, 0, sizeof(_accept_event.olp));

    DWORD bytes;
    BOOL rt = s_lpfnAcceptEx(
                  _listen_fd, s,
                  _accept_buffer,
                  0,
                  (sizeof(struct sockaddr_in) + 16),
                  (sizeof(struct sockaddr_in) + 16),
                  &bytes,
                  &_accept_event.olp
              );

    if (!rt && (WSAGetLastError() != ERROR_IO_PENDING))
    {
        dassert(false, "AcceptEx failed, err = %d", ::WSAGetLastError());
        closesocket(s);
    }
}
Example #12
0
static int iprint_job_submit(int snum, struct printjob *pjob)
{
	int		ret = 1;		/* Return value */
	http_t		*http = NULL;		/* HTTP connection to server */
	ipp_t		*request = NULL,	/* IPP Request */
			*response = NULL;	/* IPP Response */
	ipp_attribute_t	*attr;		/* Current attribute */
	cups_lang_t	*language = NULL;	/* Default language */
	char		uri[HTTP_MAX_URI]; /* printer-uri attribute */
	char 		*clientname = NULL; 	/* hostname of client for job-originating-host attribute */

	DEBUG(5,("iprint_job_submit(%d, %p (%d))\n", snum, pjob, pjob->sysjob));

       /*
	* 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;
	}

       /*
	* Build an IPP_PRINT_JOB request, which requires the following
	* attributes:
	*
	*    attributes-charset
	*    attributes-natural-language
	*    printer-uri
	*    requesting-user-name
	*    [document-data]
	*/

	request = ippNew();

	request->request.op.operation_id = IPP_PRINT_JOB;
	request->request.op.request_id   = 1;

	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);

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

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

	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
	             NULL, pjob->user);

	clientname = client_name();
	if (strcmp(clientname, "UNKNOWN") == 0) {
		clientname = client_addr();
	}

	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
	             "job-originating-host-name", NULL,
	             clientname);

	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
	             pjob->jobname);

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

	slprintf(uri, sizeof(uri) - 1, "/ipp/%s", PRINTERNAME(snum));

	if ((response = cupsDoFileRequest(http, request, uri, pjob->filename)) != NULL) {
		if (response->request.status.status_code >= IPP_OK_CONFLICT) {
			DEBUG(0,("Unable to print file to %s - %s\n", PRINTERNAME(snum),
			         ippErrorString(cupsLastError())));
		} else {
			ret = 0;
		}
	} else {
		DEBUG(0,("Unable to print file to `%s' - %s\n", PRINTERNAME(snum),
			 ippErrorString(cupsLastError())));
	}

	if ( ret == 0 )
		unlink(pjob->filename);
	/* else print_job_end will do it for us */

	if ( ret == 0 ) {

		attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER);
		if (attr != NULL && attr->group_tag == IPP_TAG_JOB)
		{
			pjob->sysjob = attr->values[0].integer;
		}
	}

 out:
	if (response)
		ippDelete(response);

	if (language)
		cupsLangFree(language);

	if (http)
		httpClose(http);

	return ret;
}
Example #13
0
/****************************************************************************
  make a connection to a service
****************************************************************************/
connection_struct *make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid, int *ecode)
{
	int snum;
	struct passwd *pass = NULL;
	BOOL guest = False;
	BOOL force = False;
	extern int Client;
	connection_struct *conn;
	int ret;

	strlower(service);

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

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

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

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

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

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

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

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

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

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

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

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

	conn->read_only = lp_readonly(snum);

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

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

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

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

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

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

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

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

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

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

	if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
		dbgtext( "%s (%s) ", remote_machine, conn->client_address );
		dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) );
		dbgtext( "as user %s ", user );
		dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
		dbgtext( "(pid %d)\n", (int)getpid() );
	}
	
	/* we've finished with the sensitive stuff */
	unbecome_user();
	
	/* Add veto/hide lists */
	if (!IS_IPC(conn) && !IS_PRINT(conn)) {
		set_namearray( &conn->veto_list, lp_veto_files(SNUM(conn)));
		set_namearray( &conn->hide_list, lp_hide_files(SNUM(conn)));
		set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(SNUM(conn)));
	}
	
	return(conn);
}
Example #14
0
static connection_struct *make_connection_snum(int snum, user_struct *vuser,
					       DATA_BLOB password, 
					       const char *pdev,
					       NTSTATUS *status)
{
	struct passwd *pass = NULL;
	BOOL guest = False;
	connection_struct *conn;
	SMB_STRUCT_STAT st;
	fstring user;
	fstring dev;
	int ret;
	struct timespec atime_ts, mtime_ts, ctime_ts;

	*user = 0;
	fstrcpy(dev, pdev);
	SET_STAT_INVALID(st);

	if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
		return NULL;
	}	

	conn = conn_new();
	if (!conn) {
		DEBUG(0,("Couldn't find free connection.\n"));
		*status = NT_STATUS_INSUFFICIENT_RESOURCES;
		return NULL;
	}

	conn->params->service = snum;
	conn->nt_user_token = NULL;

	if (lp_guest_only(snum)) {
		const char *guestname = lp_guestaccount();
		NTSTATUS status2;
		char *found_username = NULL;

		guest = True;
		pass = getpwnam_alloc(NULL, guestname);
		if (!pass) {
			DEBUG(0,("make_connection_snum: Invalid guest "
				 "account %s??\n",guestname));
			conn_free(conn);
			*status = NT_STATUS_NO_SUCH_USER;
			return NULL;
		}
		status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
						     &conn->uid, &conn->gid,
						     &found_username,
						     &conn->nt_user_token);
		if (!NT_STATUS_IS_OK(status2)) {
			TALLOC_FREE(pass);
			conn_free(conn);
			*status = status2;
			return NULL;
		}
		fstrcpy(user, found_username);
		string_set(&conn->user,user);
		conn->force_user = True;
		TALLOC_FREE(found_username);
		TALLOC_FREE(pass);
		DEBUG(3,("Guest only user %s\n",user));
	} else if (vuser) {
		if (vuser->guest) {
			if (!lp_guest_ok(snum)) {
				DEBUG(2, ("guest user (from session setup) "
					  "not permitted to access this share "
					  "(%s)\n", lp_servicename(snum)));
				      conn_free(conn);
				      *status = NT_STATUS_ACCESS_DENIED;
				      return NULL;
			}
		} else {
			if (!user_ok_token(vuser->user.unix_name,
					   vuser->nt_user_token, snum)) {
				DEBUG(2, ("user '%s' (from session setup) not "
					  "permitted to access this share "
					  "(%s)\n", vuser->user.unix_name,
					  lp_servicename(snum)));
				conn_free(conn);
				*status = NT_STATUS_ACCESS_DENIED;
				return NULL;
			}
		}
		conn->vuid = vuser->vuid;
		conn->uid = vuser->uid;
		conn->gid = vuser->gid;
		string_set(&conn->user,vuser->user.unix_name);
		fstrcpy(user,vuser->user.unix_name);
		guest = vuser->guest; 
	} else if (lp_security() == SEC_SHARE) {
		NTSTATUS status2;
		char *found_username = NULL;

		/* add it as a possible user name if we 
		   are in share mode security */
		add_session_user(lp_servicename(snum));
		/* shall we let them in? */
		if (!authorise_login(snum,user,password,&guest)) {
			DEBUG( 2, ( "Invalid username/password for [%s]\n", 
				    lp_servicename(snum)) );
			conn_free(conn);
			*status = NT_STATUS_WRONG_PASSWORD;
			return NULL;
		}
		pass = Get_Pwnam(user);
		status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
						     &conn->uid, &conn->gid,
						     &found_username,
						     &conn->nt_user_token);
		if (!NT_STATUS_IS_OK(status2)) {
			conn_free(conn);
			*status = status2;
			return NULL;
		}
		fstrcpy(user, found_username);
		string_set(&conn->user,user);
		TALLOC_FREE(found_username);
		conn->force_user = True;
	} else {
		DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
		conn_free(conn);
		*status = NT_STATUS_ACCESS_DENIED;
		return NULL;
	}

	add_session_user(user);

	safe_strcpy(conn->client_address, client_addr(), 
		    sizeof(conn->client_address)-1);
	conn->num_files_open = 0;
	conn->lastused = conn->lastused_count = time(NULL);
	conn->used = True;
	conn->printer = (strncmp(dev,"LPT",3) == 0);
	conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
		      ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
	conn->dirptr = NULL;

	/* Case options for the share. */
	if (lp_casesensitive(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_casesensitive(snum);
	}

	conn->case_preserve = lp_preservecase(snum);
	conn->short_case_preserve = lp_shortpreservecase(snum);

	conn->veto_list = NULL;
	conn->hide_list = NULL;
	conn->veto_oplock_list = NULL;
	conn->aio_write_behind_list = NULL;
	string_set(&conn->dirpath,"");
	string_set(&conn->user,user);

	conn->read_only = lp_readonly(SNUM(conn));
	conn->admin_user = False;

	/*
	 * If force user is true, then store the given userid and the gid of
	 * the user we're forcing.
	 * For auxiliary groups see below.
	 */
	
	if (*lp_force_user(snum)) {
		NTSTATUS status2;

		status2 = find_forced_user(conn,
				(vuser != NULL) && vuser->guest,
				user);
		if (!NT_STATUS_IS_OK(status2)) {
			conn_free(conn);
			*status = status2;
			return NULL;
		}
		string_set(&conn->user,user);
		conn->force_user = True;
		DEBUG(3,("Forced user %s\n",user));	  
	}

	/*
	 * If force group is true, then override
	 * any groupid stored for the connecting user.
	 */
	
	if (*lp_force_group(snum)) {
		NTSTATUS status2;
		DOM_SID group_sid;

		status2 = find_forced_group(conn->force_user,
					    snum, user,
					    &group_sid, &conn->gid);
		if (!NT_STATUS_IS_OK(status2)) {
			conn_free(conn);
			*status = status2;
			return NULL;
		}

		if ((conn->nt_user_token == NULL) && (vuser != NULL)) {

			/* Not force user and not security=share, but force
			 * group. vuser has a token to copy */
			
			conn->nt_user_token = dup_nt_token(
				NULL, vuser->nt_user_token);
			if (conn->nt_user_token == NULL) {
				DEBUG(0, ("dup_nt_token failed\n"));
				conn_free(conn);
				*status = NT_STATUS_NO_MEMORY;
				return NULL;
			}
		}

		/* If conn->nt_user_token is still NULL, we have
		 * security=share. This means ignore the SID, as we had no
		 * vuser to copy from */

		if (conn->nt_user_token != NULL) {
			/* Overwrite the primary group sid */
			sid_copy(&conn->nt_user_token->user_sids[1],
				 &group_sid);

		}
		conn->force_group = True;
	}

	if (conn->nt_user_token != NULL) {
		size_t i;

		/* We have a share-specific token from force [user|group].
		 * This means we have to create the list of unix groups from
		 * the list of sids. */

		conn->ngroups = 0;
		conn->groups = NULL;

		for (i=0; i<conn->nt_user_token->num_sids; i++) {
			gid_t gid;
			DOM_SID *sid = &conn->nt_user_token->user_sids[i];

			if (!sid_to_gid(sid, &gid)) {
				DEBUG(10, ("Could not convert SID %s to gid, "
					   "ignoring it\n",
					   sid_string_static(sid)));
				continue;
			}
			if (!add_gid_to_array_unique(conn->mem_ctx, gid, &conn->groups,
						&conn->ngroups)) {
				DEBUG(0, ("add_gid_to_array_unique failed\n"));
				conn_free(conn);
				*status = NT_STATUS_NO_MEMORY;
				return NULL;
			}
		}
	}

	{
		pstring s;
		pstrcpy(s,lp_pathname(snum));
		standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
				      conn->connectpath, conn->gid,
				      get_current_username(),
				      current_user_info.domain,
				      s, sizeof(s));

		if (s[0] == '\0') {
			DEBUG(6, ("service [%s] did not resolve to a path\n",
				lp_servicename(snum)));
			conn_free(conn);
			*status = NT_STATUS_BAD_NETWORK_NAME;
			return NULL;
		}

		set_conn_connectpath(conn,s);
		DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
			 lp_servicename(snum)));
	}

	/*
	 * New code to check if there's a share security descripter
	 * added from NT server manager. This is done after the
	 * smb.conf checks are done as we need a uid and token. JRA.
	 *
	 */

	{
		BOOL can_write = False;
		NT_USER_TOKEN *token = conn->nt_user_token ?
			conn->nt_user_token :
			(vuser ? vuser->nt_user_token : NULL);

		/*
		 * I don't believe this can happen. But the
		 * logic above is convoluted enough to confuse
		 * automated checkers, so be sure. JRA.
		 */

		if (token == NULL) {
			DEBUG(0,("make_connection: connection to %s "
				 "denied due to missing "
				 "NT token.\n",
				  lp_servicename(snum)));
			conn_free(conn);
			*status = NT_STATUS_ACCESS_DENIED;
			return NULL;
		}

		can_write = share_access_check(token,
						    lp_servicename(snum),
						    FILE_WRITE_DATA);

		if (!can_write) {
			if (!share_access_check(token,
						lp_servicename(snum),
						FILE_READ_DATA)) {
				/* No access, read or write. */
				DEBUG(0,("make_connection: connection to %s "
					 "denied due to security "
					 "descriptor.\n",
					  lp_servicename(snum)));
				conn_free(conn);
				*status = NT_STATUS_ACCESS_DENIED;
				return NULL;
			} else {
				conn->read_only = True;
			}
		}
	}
	/* Initialise VFS function pointers */

	if (!smbd_vfs_init(conn)) {
		DEBUG(0, ("vfs_init failed for service %s\n",
			  lp_servicename(snum)));
		conn_free(conn);
		*status = NT_STATUS_BAD_NETWORK_NAME;
		return NULL;
	}

	/*
	 * 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)) {
		pstring s;
		pstrcpy(s,conn->connectpath);
		canonicalize_path(conn, s);
		set_conn_connectpath(conn,s);
	}

	if ((!conn->printer) && (!conn->ipc)) {
		conn->notify_ctx = notify_init(conn->mem_ctx, server_id_self(),
					       smbd_messaging_context(),
					       smbd_event_context(),
					       conn);
	}

/* ROOT Activities: */	
	/* check number of connections */
	if (!claim_connection(conn,
			      lp_servicename(snum),
			      lp_max_connections(snum),
			      False,0)) {
		DEBUG(1,("too many connections - rejected\n"));
		conn_free(conn);
		*status = NT_STATUS_INSUFFICIENT_RESOURCES;
		return NULL;
	}  

	/* Preexecs are done here as they might make the dir we are to ChDir
	 * to below */
	/* execute any "root preexec = " line */
	if (*lp_rootpreexec(snum)) {
		pstring cmd;
		pstrcpy(cmd,lp_rootpreexec(snum));
		standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
				      conn->connectpath, conn->gid,
				      get_current_username(),
				      current_user_info.domain,
				      cmd, sizeof(cmd));
		DEBUG(5,("cmd=%s\n",cmd));
		ret = smbrun(cmd,NULL);
		if (ret != 0 && lp_rootpreexec_close(snum)) {
			DEBUG(1,("root preexec gave %d - failing "
				 "connection\n", ret));
			yield_connection(conn, lp_servicename(snum));
			conn_free(conn);
			*status = NT_STATUS_ACCESS_DENIED;
			return NULL;
		}
	}

/* 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"));
		yield_connection(conn, lp_servicename(snum));
		conn_free(conn);
		*status = NT_STATUS_LOGON_FAILURE;
		return NULL;
	}

	/* 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(snum)) {
		pstring cmd;
		pstrcpy(cmd,lp_preexec(snum));
		standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
				      conn->connectpath, conn->gid,
				      get_current_username(),
				      current_user_info.domain,
				      cmd, sizeof(cmd));
		ret = smbrun(cmd,NULL);
		if (ret != 0 && lp_preexec_close(snum)) {
			DEBUG(1,("preexec gave %d - failing connection\n",
				 ret));
			change_to_root_user();
			yield_connection(conn, lp_servicename(snum));
			conn_free(conn);
			*status = NT_STATUS_ACCESS_DENIED;
			return NULL;
		}
	}

#ifdef WITH_FAKE_KASERVER
	if (lp_afs_share(snum)) {
		afs_login(conn);
	}
#endif
	
	/* Add veto/hide lists */
	if (!IS_IPC(conn) && !IS_PRINT(conn)) {
		set_namearray( &conn->veto_list, lp_veto_files(snum));
		set_namearray( &conn->hide_list, lp_hide_files(snum));
		set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
	}
	
	/* Invoke VFS make connection hook - do this before the VFS_STAT call
	   to allow any filesystems needing user credentials to initialize
	   themselves. */

	if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
		DEBUG(0,("make_connection: VFS make connection failed!\n"));
		change_to_root_user();
		yield_connection(conn, lp_servicename(snum));
		conn_free(conn);
		*status = NT_STATUS_UNSUCCESSFUL;
		return NULL;
	}

	/* 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, conn->connectpath, &st)) != 0 ||
	    !S_ISDIR(st.st_mode)) {
		if (ret == 0 && !S_ISDIR(st.st_mode)) {
			DEBUG(0,("'%s' is not a directory, when connecting to "
				 "[%s]\n", conn->connectpath,
				 lp_servicename(snum)));
		} else {
			DEBUG(0,("'%s' does not exist or permission denied "
				 "when connecting to [%s] Error was %s\n",
				 conn->connectpath, lp_servicename(snum),
				 strerror(errno) ));
		}
		change_to_root_user();
		/* Call VFS disconnect hook */    
		SMB_VFS_DISCONNECT(conn);
		yield_connection(conn, lp_servicename(snum));
		conn_free(conn);
		*status = NT_STATUS_BAD_NETWORK_NAME;
		return NULL;
	}

	string_set(&conn->origpath,conn->connectpath);

	mtime_ts = get_mtimespec(&st);
	ctime_ts = get_ctimespec(&st);
	atime_ts = get_atimespec(&st);

	conn->ts_res = TIMESTAMP_SET_SECONDS;

	if (mtime_ts.tv_nsec ||
			atime_ts.tv_nsec ||
			ctime_ts.tv_nsec) {
		/* If any of the normal UNIX directory timestamps
		 * have a non-zero tv_nsec component assume
		 * we might be able to set sub-second timestamps.
		 * See what filetime set primitives we have.
		 */
#if defined(HAVE_UTIMES)
		/* utimes allows msec timestamps to be set. */
		conn->ts_res = TIMESTAMP_SET_MSEC;
#elif defined(HAVE_UTIME)
		/* utime only allows sec timestamps to be set. */
		conn->ts_res = TIMESTAMP_SET_SECONDS;
#endif

		/* TODO. Add a configure test for the Linux
		 * nsec timestamp set system call, and use it
		 * if available....
		 */
		DEBUG(10,("make_connection_snum: timestamp "
			"resolution of %s "
			"available on share %s, directory %s\n",
			conn->ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
			lp_servicename(conn->cnum),
			conn->connectpath ));
	}

#if SOFTLINK_OPTIMISATION
	/* resolve any soft links early if possible */
	if (vfs_ChDir(conn,conn->connectpath) == 0) {
		pstring s;
		pstrcpy(s,conn->connectpath);
		vfs_GetWd(conn,s);
		set_conn_connectpath(conn,s);
		vfs_ChDir(conn,conn->connectpath);
	}
#endif
	
	if (lp_unix_extensions() && lp_widelinks(snum)) {
		DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
			"These parameters are incompatible. "
			"Disabling wide links for this share.\n",
			lp_servicename(snum) ));
		lp_do_parameter(snum, "wide links", "False");
	}

	/*
	 * 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 : 1 ) ) {
		dbgtext( "%s (%s) ", get_remote_machine_name(),
			 conn->client_address );
		dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
		dbgtext( "connect to service %s ", lp_servicename(snum) );
		dbgtext( "initially as user %s ", user );
		dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
		dbgtext( "(pid %d)\n", (int)sys_getpid() );
	}
	
	/* we've finished with the user stuff - go back to root */
	change_to_root_user();
	return(conn);
}
Example #15
0
/* called when a session is created */
BOOL session_claim(user_struct *vuser)
{
	int i = 0;
	TDB_DATA data;
	struct sockaddr sa;
	struct in_addr *client_ip;
	struct sessionid sessionid;
	uint32 pid = (uint32)sys_getpid();
	TDB_DATA key;		
	fstring keystr;
	char * hostname;
	int tdb_store_flag;  /* If using utmp, we do an inital 'lock hold' store,
				but we don't need this if we are just using the 
				(unique) pid/vuid combination */

	vuser->session_keystr = NULL;

	/* don't register sessions for the guest user - its just too
	   expensive to go through pam session code for browsing etc */
	if (vuser->guest) {
		return True;
	}

	if (!tdb) {
		tdb = tdb_open_log(lock_path("sessionid.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, 
			       O_RDWR | O_CREAT, 0644);
		if (!tdb) {
			DEBUG(1,("session_claim: failed to open sessionid tdb\n"));
			return False;
		}
	}

	ZERO_STRUCT(sessionid);

	data.dptr = NULL;
	data.dsize = 0;

	if (lp_utmp()) {
		for (i=1;i<MAX_SESSION_ID;i++) {
			slprintf(keystr, sizeof(keystr)-1, "ID/%d", i);
			key.dptr = keystr;
			key.dsize = strlen(keystr)+1;
			
			if (tdb_store(tdb, key, data, TDB_INSERT) == 0) break;
		}
		
		if (i == MAX_SESSION_ID) {
			DEBUG(1,("session_claim: out of session IDs (max is %d)\n", 
				 MAX_SESSION_ID));
			return False;
		}
		slprintf(sessionid.id_str, sizeof(sessionid.id_str)-1, SESSION_UTMP_TEMPLATE, i);
		tdb_store_flag = TDB_MODIFY;
	} else
	{
		slprintf(keystr, sizeof(keystr)-1, "ID/%lu/%u", 
			 (long unsigned int)sys_getpid(), 
			 vuser->vuid);
		slprintf(sessionid.id_str, sizeof(sessionid.id_str)-1, 
			 SESSION_TEMPLATE, (long unsigned int)sys_getpid(), 
			 vuser->vuid);

		key.dptr = keystr;
		key.dsize = strlen(keystr)+1;
			
		tdb_store_flag = TDB_REPLACE;
	}

	/* If 'hostname lookup' == yes, then do the DNS lookup.  This is
           needed because utmp and PAM both expect DNS names 
	   
	   client_name() handles this case internally.
	*/

	hostname = client_name();
	if (strcmp(hostname, "UNKNOWN") == 0) {
		hostname = client_addr();
	}

	fstrcpy(sessionid.username, vuser->user.unix_name);
	fstrcpy(sessionid.hostname, hostname);
	sessionid.id_num = i;  /* Only valid for utmp sessions */
	sessionid.pid = pid;
	sessionid.uid = vuser->uid;
	sessionid.gid = vuser->gid;
	fstrcpy(sessionid.remote_machine, get_remote_machine_name());
	fstrcpy(sessionid.ip_addr, client_addr());

	client_ip = client_inaddr(&sa);

	if (!smb_pam_claim_session(sessionid.username, sessionid.id_str, sessionid.hostname)) {
		DEBUG(1,("pam_session rejected the session for %s [%s]\n",
				sessionid.username, sessionid.id_str));
		if (tdb_store_flag == TDB_MODIFY) {
			tdb_delete(tdb, key);
		}
		return False;
	}

	data.dptr = (char *)&sessionid;
	data.dsize = sizeof(sessionid);
	if (tdb_store(tdb, key, data, tdb_store_flag) != 0) {
		DEBUG(1,("session_claim: unable to create session id record\n"));
		return False;
	}

	if (lp_utmp()) {
		sys_utmp_claim(sessionid.username, sessionid.hostname, 
			       client_ip,
			       sessionid.id_str, sessionid.id_num);
	}

	vuser->session_keystr = strdup(keystr);
	if (!vuser->session_keystr) {
		DEBUG(0, ("session_claim:  strdup() failed for session_keystr\n"));
		return False;
	}
	return True;
}
Example #16
0
BOOL claim_connection(connection_struct *conn, const char *name,int max_connections,BOOL Clear, uint32 msg_flags)
{
	struct connections_key key;
	struct connections_data crec;
	TDB_DATA kbuf, dbuf;

	if (!tdb)
		tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, 
			       O_RDWR | O_CREAT, 0644);

	if (!tdb)
		return False;

	/*
	 * Enforce the max connections parameter.
	 */

	if (max_connections > 0) {
		struct count_stat cs;

		cs.mypid = sys_getpid();
		cs.curr_connections = 0;
		cs.name = lp_servicename(SNUM(conn));
		cs.Clear = Clear;

		/*
		 * This has a race condition, but locking the chain before hand is worse
		 * as it leads to deadlock.
		 */

		if (tdb_traverse(tdb, count_fn, &cs) == -1) {
			DEBUG(0,("claim_connection: traverse of connections.tdb failed with error %s.\n",
				tdb_errorstr(tdb) ));
			return False;
		}

		if (cs.curr_connections >= max_connections) {
			DEBUG(1,("claim_connection: Max connections (%d) exceeded for %s\n",
				max_connections, name ));
			return False;
		}
	}

	DEBUG(5,("claiming %s %d\n",name,max_connections));

	make_conn_key(conn, name, &kbuf, &key);

	/* fill in the crec */
	ZERO_STRUCT(crec);
	crec.magic = 0x280267;
	crec.pid = sys_getpid();
	crec.cnum = conn?conn->cnum:-1;
	if (conn) {
		crec.uid = conn->uid;
		crec.gid = conn->gid;
		safe_strcpy(crec.name,
			    lp_servicename(SNUM(conn)),sizeof(crec.name)-1);
	}
	crec.start = time(NULL);
	crec.bcast_msg_flags = msg_flags;
	
	safe_strcpy(crec.machine,get_remote_machine_name(),sizeof(crec.machine)-1);
	safe_strcpy(crec.addr,conn?conn->client_address:client_addr(),sizeof(crec.addr)-1);

	dbuf.dptr = (char *)&crec;
	dbuf.dsize = sizeof(crec);

	if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) {
		DEBUG(0,("claim_connection: tdb_store failed with error %s.\n",
			tdb_errorstr(tdb) ));
		return False;
	}

	return True;
}
Example #17
0
kdb_incr_result_t *
iprop_get_updates_1_svc(kdb_last_t *arg, struct svc_req *rqstp)
{
    static kdb_incr_result_t ret;
    char *whoami = "iprop_get_updates_1";
    int kret;
    kadm5_server_handle_t handle = global_server_handle;
    char *client_name = 0, *service_name = 0;
    char obuf[256] = {0};

    /* default return code */
    ret.ret = UPDATE_ERROR;

    DPRINT(("%s: start, last_sno=%lu\n", whoami,
	    (unsigned long) arg->last_sno));

    if (!handle) {
	krb5_klog_syslog(LOG_ERR,
			 _("%s: server handle is NULL"),
			 whoami);
	goto out;
    }

    {
	gss_buffer_desc client_desc, service_desc;

	if (setup_gss_names(rqstp, &client_desc, &service_desc) < 0) {
	    krb5_klog_syslog(LOG_ERR,
			     _("%s: setup_gss_names failed"),
			     whoami);
	    goto out;
	}
	client_name = buf_to_string(&client_desc);
	service_name = buf_to_string(&service_desc);
	if (client_name == NULL || service_name == NULL) {
	    free(client_name);
	    free(service_name);
	    krb5_klog_syslog(LOG_ERR,
			     "%s: out of memory recording principal names",
			     whoami);
	    goto out;
	}
    }

    DPRINT(("%s: clprinc=`%s'\n\tsvcprinc=`%s'\n",
	    whoami, client_name, service_name));

    if (!kadm5int_acl_check(handle->context,
			    rqst2name(rqstp),
			    ACL_IPROP,
			    NULL,
			    NULL)) {
	ret.ret = UPDATE_PERM_DENIED;

	krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, whoami,
			 "<null>", client_name, service_name,
			 client_addr(rqstp));
	goto out;
    }

    kret = ulog_get_entries(handle->context, *arg, &ret);

    if (ret.ret == UPDATE_OK) {
	(void) snprintf(obuf, sizeof (obuf),
			_("%s; Incoming SerialNo=%lu; Outgoing SerialNo=%lu"),
			replystr(ret.ret),
			(unsigned long)arg->last_sno,
			(unsigned long)ret.lastentry.last_sno);
    } else {
	(void) snprintf(obuf, sizeof (obuf),
			_("%s; Incoming SerialNo=%lu; Outgoing SerialNo=N/A"),
			replystr(ret.ret),
			(unsigned long)arg->last_sno);
    }

    krb5_klog_syslog(LOG_NOTICE, LOG_DONE, whoami,
		     obuf,
		     ((kret == 0) ? "success" : error_message(kret)),
		     client_name, service_name,
		     client_addr(rqstp));

out:
    if (nofork)
	debprret(whoami, ret.ret, ret.lastentry.last_sno);
    free(client_name);
    free(service_name);
    return (&ret);
}
Example #18
0
/* Callback from GSSRPC for miscellaneous errors */
static void
log_miscerr(struct svc_req *rqst, struct rpc_msg *msg, char *error, char *data)
{
    krb5_klog_syslog(LOG_NOTICE, _("Miscellaneous RPC error: %s, %s"),
                     client_addr(rqst->rq_xprt), error);
}
Example #19
0
kdb_fullresync_result_t *
iprop_full_resync_1(
	/* LINTED */
	void *argp,
	struct svc_req *rqstp)
{
	static kdb_fullresync_result_t ret;
	char tmpf[MAX_FILENAME] = {0};
	char ubuf[MAX_FILENAME + sizeof (KDB5_UTIL_DUMP_STR)] = {0};
	char clhost[MAXHOSTNAMELEN] = {0};
	int pret, fret;
	kadm5_server_handle_t handle = global_server_handle;
	OM_uint32 min_stat;
	gss_name_t name = NULL;
	char *client_name = NULL, *service_name = NULL;
	char *whoami = "iprop_full_resync_1";

	/* default return code */
	ret.ret = UPDATE_ERROR;

	if (!handle) {
		krb5_klog_syslog(LOG_ERR,
				gettext("%s: server handle is NULL"),
					whoami);
		goto out;
	}

	DPRINT(("%s: start\n", whoami));

	if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
		krb5_klog_syslog(LOG_ERR,
			gettext("%s: setup_gss_names failed"),
			whoami);
		goto out;
	}

	DPRINT(("%s: clprinc=`%s'\n\tsvcprinc=`%s'\n",
		whoami, client_name, service_name));

	if (!(name = get_clnt_name(rqstp))) {
		krb5_klog_syslog(LOG_ERR,
			gettext("%s: Couldn't obtain client's name"),
			whoami);
		goto out;
	}
	if (!kadm5int_acl_check(handle->context,
		    name,
		    ACL_IPROP,
		    NULL,
		    NULL)) {
		ret.ret = UPDATE_PERM_DENIED;

		audit_kadmind_unauth(rqstp->rq_xprt, l_port,
				    whoami,
				    "<null>", client_name);
		krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, whoami,
				"<null>", client_name, service_name,
				client_addr(rqstp, abuf));
		goto out;
	}

	if (!getclhoststr(client_name, clhost, sizeof (clhost))) {
		krb5_klog_syslog(LOG_ERR,
			gettext("%s: getclhoststr failed"),
			whoami);
		goto out;
	}

	/*
	 * construct db dump file name; kprop style name + clnt fqdn
	 */
	(void) strcpy(tmpf, "/var/krb5/slave_datatrans_");
	if (strlcat(tmpf, clhost, sizeof (tmpf)) >= sizeof (tmpf)) {
		krb5_klog_syslog(LOG_ERR,
		gettext("%s: db dump file name too long; max length=%d"),
				whoami,
				(sizeof (tmpf) - 1));
		goto out;
	}

	/*
	 * note the -i; modified version of kdb5_util dump format
	 * to include sno (serial number)
	 */
	if (strlcpy(ubuf, KDB5_UTIL_DUMP_STR, sizeof (ubuf)) >=
	    sizeof (ubuf)) {
		goto out;
	}
	if (strlcat(ubuf, tmpf, sizeof (ubuf)) >= sizeof (ubuf)) {
		krb5_klog_syslog(LOG_ERR,
		gettext("%s: kdb5 util dump string too long; max length=%d"),
				whoami,
				(sizeof (ubuf) - 1));
		goto out;
	}

	/*
	 * Fork to dump the db and xfer it to the slave.
	 * (the fork allows parent to return quickly and the child
	 * acts like a callback to the slave).
	 */
	fret = fork();
	DPRINT(("%s: fork=%d (%d)\n", whoami, fret, getpid()));

	switch (fret) {
	case -1: /* error */
		if (nofork) {
			perror(whoami);
		}
		krb5_klog_syslog(LOG_ERR,
				gettext("%s: fork failed: %s"),
				whoami,
				error_message(errno));
		goto out;

	case 0: /* child */
		DPRINT(("%s: run `%s' ...\n", whoami, ubuf));
#ifdef POSIX_SIGNALS
		(void) sigemptyset(&s_action.sa_mask);
		s_action.sa_handler = SIG_DFL;
		(void) sigaction(SIGCHLD, &s_action, (struct sigaction *) NULL);
#else
		(void) signal(SIGCHLD, SIG_DFL);
#endif /* POSIX_SIGNALS */
		/* run kdb5_util(1M) dump for IProp */
		pret = pclose(popen(ubuf, "w"));
		DPRINT(("%s: pclose=%d\n", whoami, pret));
		if (pret == -1) {
			if (nofork) {
				perror(whoami);
			}
			krb5_klog_syslog(LOG_ERR,
				gettext("%s: pclose(popen) failed: %s"),
					whoami,
					error_message(errno));
			goto out;
		}

		DPRINT(("%s: exec `kprop -f %s %s' ...\n",
			whoami, tmpf, clhost));
		pret = execl("/usr/lib/krb5/kprop", "kprop", "-f", tmpf,
			    clhost, NULL);
		if (pret == -1) {
			if (nofork) {
				perror(whoami);
			}
			krb5_klog_syslog(LOG_ERR,
					gettext("%s: exec failed: %s"),
					whoami,
					error_message(errno));
			goto out;
		}

	default: /* parent */
		ret.ret = UPDATE_OK;
		/* not used by slave (sno is retrieved from kdb5_util dump) */
		ret.lastentry.last_sno = 0;
		ret.lastentry.last_time.seconds = 0;
		ret.lastentry.last_time.useconds = 0;

		audit_kadmind_auth(rqstp->rq_xprt, l_port,
				whoami,
				"<null>", client_name, 0);

		krb5_klog_syslog(LOG_NOTICE, LOG_DONE, whoami,
				"<null>",
				"success",
				client_name, service_name,
				client_addr(rqstp, abuf));

		goto out;
	}

out:
	if (nofork)
		debprret(whoami, ret.ret, 0);
	if (client_name)
		free(client_name);
	if (service_name)
		free(service_name);
	if (name)
		gss_release_name(&min_stat, &name);
	return (&ret);
}
Example #20
0
connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
					int snum, user_struct *vuser,
					DATA_BLOB password,
					const char *pdev,
					NTSTATUS *pstatus)
{
	connection_struct *conn;
	struct smb_filename *smb_fname_cpath = NULL;
	fstring dev;
	int ret;
	char addr[INET6_ADDRSTRLEN];
	bool on_err_call_dis_hook = false;
	NTSTATUS status;

	fstrcpy(dev, pdev);

	if (NT_STATUS_IS_ERR(*pstatus = share_sanity_checks(snum, dev))) {
		return NULL;
	}	

	conn = conn_new(sconn);
	if (!conn) {
		DEBUG(0,("Couldn't find free connection.\n"));
		*pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
		return NULL;
	}

	conn->params->service = snum;

	status = create_connection_server_info(sconn,
		conn, snum, vuser ? vuser->server_info : NULL, password,
		&conn->server_info);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("create_connection_server_info failed: %s\n",
			  nt_errstr(status)));
		*pstatus = status;
		conn_free(conn);
		return NULL;
	}

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

	add_session_user(sconn, conn->server_info->unix_name);

	safe_strcpy(conn->client_address,
			client_addr(get_client_fd(),addr,sizeof(addr)), 
			sizeof(conn->client_address)-1);
	conn->num_files_open = 0;
	conn->lastused = conn->lastused_count = time(NULL);
	conn->used = True;
	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_casesensitive(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_casesensitive(snum);
	}

	conn->case_preserve = lp_preservecase(snum);
	conn->short_case_preserve = lp_shortpreservecase(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_readonly(SNUM(conn));
	conn->admin_user = False;

	if (*lp_force_user(snum)) {

		/*
		 * Replace conn->server_info with a completely faked up one
		 * from the username we are forced into :-)
		 */

		char *fuser;
		struct auth_serversupplied_info *forced_serverinfo;

		fuser = talloc_string_sub(conn, lp_force_user(snum), "%S",
					  lp_servicename(snum));
		if (fuser == NULL) {
			conn_free(conn);
			*pstatus = NT_STATUS_NO_MEMORY;
			return NULL;
		}

		status = make_serverinfo_from_username(
			conn, fuser, conn->server_info->guest,
			&forced_serverinfo);
		if (!NT_STATUS_IS_OK(status)) {
			conn_free(conn);
			*pstatus = status;
			return NULL;
		}

		TALLOC_FREE(conn->server_info);
		conn->server_info = forced_serverinfo;

		conn->force_user = True;
		DEBUG(3,("Forced user %s\n", fuser));
	}

	/*
	 * If force group is true, then override
	 * any groupid stored for the connecting user.
	 */

	if (*lp_force_group(snum)) {

		status = find_forced_group(
			conn->force_user, snum, conn->server_info->unix_name,
			&conn->server_info->ptok->user_sids[1],
			&conn->server_info->utok.gid);

		if (!NT_STATUS_IS_OK(status)) {
			conn_free(conn);
			*pstatus = status;
			return NULL;
		}

		/*
		 * We need to cache this gid, to use within
 		 * change_to_user() separately from the conn->server_info
 		 * struct. We only use conn->server_info directly if
 		 * "force_user" was set.
 		 */
		conn->force_group_gid = conn->server_info->utok.gid;
	}

	conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID;

	{
		char *s = talloc_sub_advanced(talloc_tos(),
					lp_servicename(SNUM(conn)),
					conn->server_info->unix_name,
					conn->connectpath,
					conn->server_info->utok.gid,
					conn->server_info->sanitized_username,
					pdb_get_domain(conn->server_info->sam_account),
					lp_pathname(snum));
		if (!s) {
			conn_free(conn);
			*pstatus = NT_STATUS_NO_MEMORY;
			return NULL;
		}

		if (!set_conn_connectpath(conn,s)) {
			TALLOC_FREE(s);
			conn_free(conn);
			*pstatus = NT_STATUS_NO_MEMORY;
			return NULL;
		}
		DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
			 lp_servicename(snum)));
		TALLOC_FREE(s);
	}

	/*
	 * New code to check if there's a share security descripter
	 * added from NT server manager. This is done after the
	 * smb.conf checks are done as we need a uid and token. JRA.
	 *
	 */

	{
		bool can_write = False;

		can_write = share_access_check(conn->server_info->ptok,
					       lp_servicename(snum),
					       FILE_WRITE_DATA);

		if (!can_write) {
			if (!share_access_check(conn->server_info->ptok,
						lp_servicename(snum),
						FILE_READ_DATA)) {
				/* No access, read or write. */
				DEBUG(0,("make_connection: connection to %s "
					 "denied due to security "
					 "descriptor.\n",
					  lp_servicename(snum)));
				conn_free(conn);
				*pstatus = NT_STATUS_ACCESS_DENIED;
				return NULL;
			} else {
				conn->read_only = True;
			}
		}
	}
	/* Initialise VFS function pointers */

	if (!smbd_vfs_init(conn)) {
		DEBUG(0, ("vfs_init failed for service %s\n",
			  lp_servicename(snum)));
		conn_free(conn);
		*pstatus = NT_STATUS_BAD_NETWORK_NAME;
		return NULL;
	}

	/*
	 * 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(snum),
				conn->connectpath));
			conn_free(conn);
			*pstatus = NT_STATUS_BAD_NETWORK_NAME;
			return NULL;
		}
	}

	if ((!conn->printer) && (!conn->ipc)) {
		conn->notify_ctx = notify_init(conn, server_id_self(),
					       smbd_messaging_context(),
					       smbd_event_context(),
					       conn);
	}

/* ROOT Activities: */	
	/*
	 * Enforce the max connections parameter.
	 */

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

		DEBUG(1, ("Max connections (%d) exceeded for %s\n",
			  lp_max_connections(snum), lp_servicename(snum)));
		conn_free(conn);
		*pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
		return NULL;
	}  

	/*
	 * Get us an entry in the connections db
	 */
	if (!claim_connection(conn, lp_servicename(snum), 0)) {
		DEBUG(1, ("Could not store connections entry\n"));
		conn_free(conn);
		*pstatus = NT_STATUS_INTERNAL_DB_ERROR;
		return NULL;
	}  

	/* Preexecs are done here as they might make the dir we are to ChDir
	 * to below */
	/* execute any "root preexec = " line */
	if (*lp_rootpreexec(snum)) {
		char *cmd = talloc_sub_advanced(talloc_tos(),
					lp_servicename(SNUM(conn)),
					conn->server_info->unix_name,
					conn->connectpath,
					conn->server_info->utok.gid,
					conn->server_info->sanitized_username,
					pdb_get_domain(conn->server_info->sam_account),
					lp_rootpreexec(snum));
		DEBUG(5,("cmd=%s\n",cmd));
		ret = smbrun(cmd,NULL);
		TALLOC_FREE(cmd);
		if (ret != 0 && lp_rootpreexec_close(snum)) {
			DEBUG(1,("root preexec gave %d - failing "
				 "connection\n", ret));
			yield_connection(conn, lp_servicename(snum));
			conn_free(conn);
			*pstatus = NT_STATUS_ACCESS_DENIED;
			return NULL;
		}
	}

/* 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"));
		yield_connection(conn, lp_servicename(snum));
		conn_free(conn);
		*pstatus = NT_STATUS_LOGON_FAILURE;
		return NULL;
	}

	/* 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(snum)) {
		char *cmd = talloc_sub_advanced(talloc_tos(),
					lp_servicename(SNUM(conn)),
					conn->server_info->unix_name,
					conn->connectpath,
					conn->server_info->utok.gid,
					conn->server_info->sanitized_username,
					pdb_get_domain(conn->server_info->sam_account),
					lp_preexec(snum));
		ret = smbrun(cmd,NULL);
		TALLOC_FREE(cmd);
		if (ret != 0 && lp_preexec_close(snum)) {
			DEBUG(1,("preexec gave %d - failing connection\n",
				 ret));
			*pstatus = NT_STATUS_ACCESS_DENIED;
			goto err_root_exit;
		}
	}

#ifdef WITH_FAKE_KASERVER
	if (lp_afs_share(snum)) {
		afs_login(conn);
	}
#endif
	
	/* Add veto/hide lists */
	if (!IS_IPC(conn) && !IS_PRINT(conn)) {
		set_namearray( &conn->veto_list, lp_veto_files(snum));
		set_namearray( &conn->hide_list, lp_hide_files(snum));
		set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
		set_namearray( &conn->aio_write_behind_list,
				lp_aio_write_behind(snum));
	}
	
	/* Invoke VFS make connection hook - do this before the VFS_STAT call
	   to allow any filesystems needing user credentials to initialize
	   themselves. */

	if (SMB_VFS_CONNECT(conn, lp_servicename(snum),
			    conn->server_info->unix_name) < 0) {
		DEBUG(0,("make_connection: VFS make connection failed!\n"));
		*pstatus = NT_STATUS_UNSUCCESSFUL;
		goto err_root_exit;
	}

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

	status = create_synthetic_smb_fname(talloc_tos(), conn->connectpath,
					    NULL, NULL, &smb_fname_cpath);
	if (!NT_STATUS_IS_OK(status)) {
		*pstatus = status;
		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(snum)));
		} else {
			DEBUG(0,("'%s' does not exist or permission denied "
				 "when connecting to [%s] Error was %s\n",
				 conn->connectpath, lp_servicename(snum),
				 strerror(errno) ));
		}
		*pstatus = NT_STATUS_BAD_NETWORK_NAME;
		goto err_root_exit;
	}

	string_set(&conn->origpath,conn->connectpath);

#if SOFTLINK_OPTIMISATION
	/* resolve any soft links early if possible */
	if (vfs_ChDir(conn,conn->connectpath) == 0) {
		TALLOC_CTX *ctx = talloc_tos();
		char *s = vfs_GetWd(ctx,s);
		if (!s) {
			*status = map_nt_error_from_unix(errno);
			goto err_root_exit;
		}
		if (!set_conn_connectpath(conn,s)) {
			*status = NT_STATUS_NO_MEMORY;
			goto err_root_exit;
		}
		vfs_ChDir(conn,conn->connectpath);
	}
#endif

	if (lp_unix_extensions() && lp_widelinks(snum)) {
		DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
			"These parameters are incompatible. "
			"Disabling wide links for this share.\n",
			lp_servicename(snum) ));
		lp_do_parameter(snum, "wide links", "False");
	}

	/* 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 : 1 ) ) {
		dbgtext( "%s (%s) ", get_remote_machine_name(),
			 conn->client_address );
		dbgtext( "%s", srv_is_signing_active(smbd_server_conn) ? "signed " : "");
		dbgtext( "connect to service %s ", lp_servicename(snum) );
		dbgtext( "initially as user %s ",
			 conn->server_info->unix_name );
		dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
		dbgtext( "(pid %d)\n", (int)sys_getpid() );
	}

	/* we've finished with the user stuff - go back to root */
	change_to_root_user();
	return(conn);

  err_root_exit:
	TALLOC_FREE(smb_fname_cpath);
	change_to_root_user();
	if (on_err_call_dis_hook) {
		/* Call VFS disconnect hook */
		SMB_VFS_DISCONNECT(conn);
	}
	yield_connection(conn, lp_servicename(snum));
	conn_free(conn);
	return NULL;
}
Example #21
0
void standard_sub_basic(const char *smb_name, char *str,size_t len)
{
	char *p, *s;
	fstring pidstr;
	struct passwd *pass;
	const char *local_machine_name = get_local_machine_name();

	for (s=str; (p=strchr_m(s, '%'));s=p) {
		fstring tmp_str;

		int l = (int)len - (int)(p-str);

		if (l < 0)
			l = 0;
		
		switch (*(p+1)) {
		case 'U' : 
			fstrcpy(tmp_str, smb_name);
			strlower_m(tmp_str);
			string_sub(p,"%U",tmp_str,l);
			break;
		case 'G' :
			fstrcpy(tmp_str, smb_name);
			if ((pass = Get_Pwnam(tmp_str))!=NULL) {
				string_sub(p,"%G",gidtoname(pass->pw_gid),l);
			} else {
				p += 2;
			}
			break;
		case 'D' :
			fstrcpy(tmp_str, current_user_info.domain);
			strupper_m(tmp_str);
			string_sub(p,"%D", tmp_str,l);
			break;
		case 'I' :
			string_sub(p,"%I", client_addr(),l);
			break;
		case 'i' :
			string_sub(p,"%i", client_socket_addr(),l);
			break;
		case 'L' : 
			if (local_machine_name && *local_machine_name)
				string_sub(p,"%L", local_machine_name,l); 
			else {
				pstring temp_name;

				pstrcpy(temp_name, global_myname());
				strlower_m(temp_name);
				string_sub(p,"%L", temp_name,l); 
			}
			break;
		case 'M' :
			string_sub(p,"%M", client_name(),l);
			break;
		case 'R' :
			string_sub(p,"%R", remote_proto,l);
			break;
		case 'T' :
			string_sub(p,"%T", timestring(False),l);
			break;
		case 'a' :
			string_sub(p,"%a", remote_arch,l);
			break;
		case 'd' :
			slprintf(pidstr,sizeof(pidstr)-1, "%d",(int)sys_getpid());
			string_sub(p,"%d", pidstr,l);
			break;
		case 'h' :
			string_sub(p,"%h", myhostname(),l);
			break;
		case 'm' :
			string_sub(p,"%m", get_remote_machine_name(),l);
			break;
		case 'v' :
			string_sub(p,"%v", SAMBA_VERSION_STRING,l);
			break;
		case '$' :
			p += expand_env_var(p,l);
			break; /* Expand environment variables */
		case '\0': 
			p++; 
			break; /* don't run off the end of the string */
			
		default: p+=2; 
			break;
		}
	}
}
Example #22
0
void MyCacheServer::run()
{
	if (!clients_socket_ || !workers_socket_) 
		return;

	//  Logic of LRU loop
    //  - Poll backend always, frontend only if 1+ worker ready
    //  - If worker replies, queue worker as ready and forward reply
    //    to client if necessary
    //  - If client requests, pop next worker and send request to it
    //
    //  A very simple queue structure with known max size
    std::vector<std::string> worker_queue;
    size_t worker_queue_selector = 0;

    //  Initialize poll set
    zmq::pollitem_t items[] = {
        	//  Always poll for worker activity on backend
            { *workers_socket_, 0, ZMQ_POLLIN, 0 },
            //  Poll front-end only if we have available workers
            { *clients_socket_, 0, ZMQ_POLLIN, 0 }
    };

    while (!s_interrupted) 
    {
    	try 
    	{
	        if (worker_queue.size())
	            zmq::poll(&items[0], 2, 100);
	        else
	            zmq::poll(&items[0], 1, 100);

	        //  Handle worker activity on backend
	        if (items[0].revents & ZMQ_POLLIN) 
	        {
	            //  Queue worker address for LRU routing
	            zmq::message_t worker_addr;
	            workers_socket_->recv(&worker_addr);

	            //  Second frame is empty
	            {
		            zmq::message_t empty;
		            workers_socket_->recv(&empty);
	        	}
	      
	            //  Third frame is READY or else a client reply address
	            zmq::message_t client_addr_msg;
	            workers_socket_->recv(&client_addr_msg);
	            std::string client_addr((char*)client_addr_msg.data(), client_addr_msg.size());

	            //  If client reply, send rest back to frontend
	            if (client_addr.compare("READY") != 0) 
	            {
	            	// empty frame
	            	{
		            	zmq::message_t empty;
		            	workers_socket_->recv(&empty);
	            	}

	            	zmq::message_t reply;
	            	workers_socket_->recv(&reply);

	            	// std::string ret((char*)reply.data(), reply.size());
	            	// std::cout << "frontend->client:" << ret << std::endl;

	            	clients_socket_->send(client_addr_msg, ZMQ_SNDMORE);
	            	
	            	// Sync Client(REQ)
	            	if (client_addr[0] != '_')
	            	{
	            		zmq::message_t empty;
	            		clients_socket_->send(empty, ZMQ_SNDMORE);
	            	}

	            	clients_socket_->send(reply);
	            }
	            else
	            {
	            	worker_queue.push_back(std::string((char*)worker_addr.data(), worker_addr.size()));
	            }
	        }
	        if (items[1].revents & ZMQ_POLLIN) 
	        {

	            //  Now get next client request, route to LRU worker
	            //  Client request is [address][empty][request]
	            zmq::message_t client_addr_msg;
	            clients_socket_->recv(&client_addr_msg);
	            std::string id((char*)client_addr_msg.data(), client_addr_msg.size());

	            // Sync Client(REQ)
	            if (id[0] != '_')
	            {
	            	zmq::message_t empty;
	            	clients_socket_->recv(&empty);
	            }

	            zmq::message_t request;
	            clients_socket_->recv(&request);
	            
	            if (worker_queue.size() > 0)
	            {
		            std::string worker_addr = worker_queue[(worker_queue_selector++) % worker_queue.size()];

		            zmq::message_t empty;
		            workers_socket_->send(worker_addr.data(), worker_addr.size(), ZMQ_SNDMORE);
		           	workers_socket_->send(empty, ZMQ_SNDMORE);
		            workers_socket_->send(client_addr_msg, ZMQ_SNDMORE);
		            workers_socket_->send(empty, ZMQ_SNDMORE);
		            workers_socket_->send(request);
	        	}
	        }
    	}
    	catch (const std::exception& err)
    	{
    		LOG4CXX_ERROR(logger, "server run failed:" << err.what());
    		break;
    	}
    }

    LOG4CXX_INFO(logger, "server will be shutdown");

    fini();
}
Example #23
0
kdb_fullresync_result_t *
iprop_full_resync_1_svc(/* LINTED */ void *argp, struct svc_req *rqstp)
{
    static kdb_fullresync_result_t ret;
    char *tmpf = 0;
    char *ubuf = 0;
    char clhost[MAXHOSTNAMELEN] = {0};
    int pret, fret;
    kadm5_server_handle_t handle = global_server_handle;
    OM_uint32 min_stat;
    gss_name_t name = NULL;
    char *client_name = NULL, *service_name = NULL;
    char *whoami = "iprop_full_resync_1";

    /* default return code */
    ret.ret = UPDATE_ERROR;

    if (!handle) {
	krb5_klog_syslog(LOG_ERR,
			 _("%s: server handle is NULL"),
			 whoami);
	goto out;
    }

    DPRINT(("%s: start\n", whoami));

    {
	gss_buffer_desc client_desc, service_desc;

	if (setup_gss_names(rqstp, &client_desc, &service_desc) < 0) {
	    krb5_klog_syslog(LOG_ERR,
			     _("%s: setup_gss_names failed"),
			     whoami);
	    goto out;
	}
	client_name = buf_to_string(&client_desc);
	service_name = buf_to_string(&service_desc);
	if (client_name == NULL || service_name == NULL) {
	    free(client_name);
	    free(service_name);
	    krb5_klog_syslog(LOG_ERR,
			     "%s: out of memory recording principal names",
			     whoami);
	    goto out;
	}
    }

    DPRINT(("%s: clprinc=`%s'\n\tsvcprinc=`%s'\n",
	    whoami, client_name, service_name));

    if (!kadm5int_acl_check(handle->context,
			    rqst2name(rqstp),
			    ACL_IPROP,
			    NULL,
			    NULL)) {
	ret.ret = UPDATE_PERM_DENIED;

	krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, whoami,
			 "<null>", client_name, service_name,
			 client_addr(rqstp));
	goto out;
    }

    if (!getclhoststr(client_name, clhost, sizeof (clhost))) {
	krb5_klog_syslog(LOG_ERR,
			 _("%s: getclhoststr failed"),
			 whoami);
	goto out;
    }

    /*
     * construct db dump file name; kprop style name + clnt fqdn
     */
    if (asprintf(&tmpf, "%s_%s", KPROP_DEFAULT_FILE, clhost) < 0) {
	krb5_klog_syslog(LOG_ERR,
			 _("%s: unable to construct db dump file name; out of memory"),
			 whoami);
	goto out;
    }

    /*
     * note the -i; modified version of kdb5_util dump format
     * to include sno (serial number)
     */
    if (asprintf(&ubuf, "%s dump -i %s", KPROPD_DEFAULT_KDB5_UTIL,
		 tmpf) < 0) {
	krb5_klog_syslog(LOG_ERR,
			 _("%s: cannot construct kdb5 util dump string too long; out of memory"),
			 whoami);
	goto out;
    }

    /*
     * Fork to dump the db and xfer it to the slave.
     * (the fork allows parent to return quickly and the child
     * acts like a callback to the slave).
     */
    fret = fork();
    DPRINT(("%s: fork=%d (%d)\n", whoami, fret, getpid()));

    switch (fret) {
    case -1: /* error */
	if (nofork) {
	    perror(whoami);
	}
	krb5_klog_syslog(LOG_ERR,
			 _("%s: fork failed: %s"),
			 whoami,
			 error_message(errno));
	goto out;

    case 0: /* child */
	DPRINT(("%s: run `%s' ...\n", whoami, ubuf));
	(void) signal(SIGCHLD, SIG_DFL);
	/* run kdb5_util(1M) dump for IProp */
	/* XXX popen can return NULL; is pclose(NULL) okay?  */
	pret = pclose(popen(ubuf, "w"));
	DPRINT(("%s: pclose=%d\n", whoami, pret));
	if (pret != 0) {
	    /* XXX popen/pclose may not set errno
	       properly, and the error could be from the
	       subprocess anyways.  */
	    if (nofork) {
		perror(whoami);
	    }
	    krb5_klog_syslog(LOG_ERR,
			     _("%s: pclose(popen) failed: %s"),
			     whoami,
			     error_message(errno));
	    goto out;
	}

	DPRINT(("%s: exec `kprop -f %s %s' ...\n",
		whoami, tmpf, clhost));
	/* XXX Yuck!  */
	if (getenv("KPROP_PORT"))
	    pret = execl(KPROPD_DEFAULT_KPROP, "kprop", "-f", tmpf,
			 "-P", getenv("KPROP_PORT"),
			 clhost, NULL);
	else
	    pret = execl(KPROPD_DEFAULT_KPROP, "kprop", "-f", tmpf,
			 clhost, NULL);
	if (pret == -1) {
	    if (nofork) {
		perror(whoami);
	    }
	    krb5_klog_syslog(LOG_ERR,
			     _("%s: exec failed: %s"),
			     whoami,
			     error_message(errno));
	    goto out;
	}

    default: /* parent */
	ret.ret = UPDATE_OK;
	/* not used by slave (sno is retrieved from kdb5_util dump) */
	ret.lastentry.last_sno = 0;
	ret.lastentry.last_time.seconds = 0;
	ret.lastentry.last_time.useconds = 0;

	krb5_klog_syslog(LOG_NOTICE, LOG_DONE, whoami,
			 "<null>",
			 "success",
			 client_name, service_name,
			 client_addr(rqstp));

	goto out;
    }

out:
    if (nofork)
	debprret(whoami, ret.ret, 0);
    free(client_name);
    free(service_name);
    if (name)
	gss_release_name(&min_stat, &name);
    free(tmpf);
    free(ubuf);
    return (&ret);
}
Example #24
0
static kdb_fullresync_result_t *
ipropx_resync(uint32_t vers, struct svc_req *rqstp)
{
    static kdb_fullresync_result_t ret;
    char *ubuf = 0;
    char clhost[MAXHOSTNAMELEN] = {0};
    int pret, fret;
    FILE *p;
    kadm5_server_handle_t handle = global_server_handle;
    OM_uint32 min_stat;
    gss_name_t name = NULL;
    char *client_name = NULL, *service_name = NULL;
    char *whoami = "iprop_full_resync_1";

    /*
     * vers contains the highest version number the client is
     * willing to accept. A client can always accept a lower
     * version: the version number is indicated in the dump
     * header.
     */

    /* default return code */
    ret.ret = UPDATE_ERROR;

    if (!handle) {
	krb5_klog_syslog(LOG_ERR,
			 _("%s: server handle is NULL"),
			 whoami);
	goto out;
    }

    DPRINT("%s: start\n", whoami);

    {
	gss_buffer_desc client_desc, service_desc;

	if (setup_gss_names(rqstp, &client_desc, &service_desc) < 0) {
	    DPRINT("%s: setup_gss_names failed\n", whoami);
	    krb5_klog_syslog(LOG_ERR,
			     _("%s: setup_gss_names failed"),
			     whoami);
	    goto out;
	}
	client_name = buf_to_string(&client_desc);
	service_name = buf_to_string(&service_desc);
	if (client_name == NULL || service_name == NULL) {
	    free(client_name);
	    free(service_name);
	    DPRINT("%s: out of memory\n", whoami);
	    krb5_klog_syslog(LOG_ERR,
			     _("%s: out of memory recording principal names"),
			     whoami);
	    goto out;
	}
    }

    DPRINT("%s: clprinc=`%s'\n\tsvcprinc=`%s'\n",
	    whoami, client_name, service_name);

    if (!kadm5int_acl_check(handle->context,
			    rqst2name(rqstp),
			    ACL_IPROP,
			    NULL,
			    NULL)) {
	ret.ret = UPDATE_PERM_DENIED;

	DPRINT("%s: Permission denied\n", whoami);
	krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, whoami,
			 client_name, service_name,
			 client_addr(rqstp));
	goto out;
    }

    if (!getclhoststr(client_name, clhost, sizeof (clhost))) {
	krb5_klog_syslog(LOG_ERR,
			 _("%s: getclhoststr failed"),
			 whoami);
	goto out;
    }

    /*
     * Note the -i; modified version of kdb5_util dump format
     * to include sno (serial number). This argument is now
     * versioned (-i0 for legacy dump format, -i1 for ipropx
     * version 1 format, etc).
     *
     * The -c option ("conditional") causes the dump to dump only if no
     * dump already exists or that dump is not in ipropx format, or the
     * sno and timestamp in the header of that dump are outside the
     * ulog.  This allows us to share a single global dump with all
     * slaves, since it's OK to share an older dump, as long as its sno
     * and timestamp are in the ulog (then the slaves can get the
     * subsequent updates very iprop).
     */
    if (asprintf(&ubuf, "%s dump -i%d -c %s",
		 kdb5_util, vers, dump_file) < 0) {
	krb5_klog_syslog(LOG_ERR,
			 _("%s: cannot construct kdb5 util dump string too long; out of memory"),
			 whoami);
	goto out;
    }

    /*
     * Fork to dump the db and xfer it to the slave.
     * (the fork allows parent to return quickly and the child
     * acts like a callback to the slave).
     */
    fret = fork();
    DPRINT("%s: fork=%d (%d)\n", whoami, fret, getpid());

    switch (fret) {
    case -1: /* error */
	if (nofork) {
	    perror(whoami);
	}
	DPRINT("%s: fork failed\n", whoami);
	krb5_klog_syslog(LOG_ERR,
			 _("%s: fork failed: %s"),
			 whoami,
			 error_message(errno));
	goto out;

    case 0: /* child */
	DPRINT("%s: run `%s' ...\n", whoami, ubuf);
	(void) signal(SIGCHLD, SIG_DFL);
	/* run kdb5_util(1M) dump for IProp */
	p = popen(ubuf, "w");
	if (p == NULL) {
	    krb5_klog_syslog(LOG_ERR,
			     _("%s: popen failed: %s"),
			     whoami, error_message(errno));
	    _exit(1);
	}
	pret = pclose(p);
	DPRINT("%s: pclose=%d\n", whoami, pret);
	if (pret != 0) {
	    /* XXX popen/pclose may not set errno
	       properly, and the error could be from the
	       subprocess anyways.  */
	    if (nofork) {
		perror(whoami);
	    }
	    krb5_klog_syslog(LOG_ERR,
			     _("%s: pclose(popen) failed: %s"),
			     whoami,
			     error_message(errno));
	    _exit(1);
	}

	DPRINT("%s: exec `kprop -f %s %s' ...\n",
		whoami, dump_file, clhost);
	/* XXX Yuck!  */
	if (getenv("KPROP_PORT")) {
	    pret = execl(kprop, "kprop", "-f", dump_file, "-P",
			 getenv("KPROP_PORT"), clhost, NULL);
	} else {
	    pret = execl(kprop, "kprop", "-f", dump_file, clhost, NULL);
	}
	perror(whoami);
	krb5_klog_syslog(LOG_ERR,
			 _("%s: exec failed: %s"),
			 whoami,
			 error_message(errno));
	_exit(1);

    default: /* parent */
	ret.ret = UPDATE_OK;
	/* not used by slave (sno is retrieved from kdb5_util dump) */
	ret.lastentry.last_sno = 0;
	ret.lastentry.last_time.seconds = 0;
	ret.lastentry.last_time.useconds = 0;

	DPRINT("%s: spawned resync process %d, client=%s, "
		"service=%s, addr=%s\n", whoami, fret, client_name,
		service_name, client_addr(rqstp));
	krb5_klog_syslog(LOG_NOTICE,
			 _("Request: %s, spawned resync process %d, client=%s, service=%s, addr=%s"),
			 whoami, fret,
			 client_name, service_name,
			 client_addr(rqstp));

	goto out;
    }

out:
    if (nofork)
	debprret(whoami, ret.ret, 0);
    free(client_name);
    free(service_name);
    if (name)
	gss_release_name(&min_stat, &name);
    free(ubuf);
    return (&ret);
}
Example #25
0
kdb_incr_result_t *
iprop_get_updates_1(kdb_last_t *arg, struct svc_req *rqstp)
{
	static kdb_incr_result_t ret;
	char *whoami = "iprop_get_updates_1";
	int kret;
	kadm5_server_handle_t handle = global_server_handle;
	char *client_name = NULL, *service_name = NULL;
	gss_name_t name = NULL;
	OM_uint32 min_stat;
	char obuf[256] = {0};

	/* default return code */
	ret.ret = UPDATE_ERROR;

	DPRINT(("%s: start, last_sno=%u\n", whoami, (ulong_t)arg->last_sno));

	if (!handle) {
		krb5_klog_syslog(LOG_ERR,
				gettext("%s: server handle is NULL"),
					whoami);
		goto out;
	}

	if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
		krb5_klog_syslog(LOG_ERR,
			gettext("%s: setup_gss_names failed"),
			whoami);
		goto out;
	}

	DPRINT(("%s: clprinc=`%s'\n\tsvcprinc=`%s'\n",
		whoami, client_name, service_name));

	if (!(name = get_clnt_name(rqstp))) {
		krb5_klog_syslog(LOG_ERR,
			gettext("%s: Couldn't obtain client's name"),
			whoami);
		goto out;
	}
	if (!kadm5int_acl_check(handle->context,
		    name,
		    ACL_IPROP,
		    NULL,
		    NULL)) {
		ret.ret = UPDATE_PERM_DENIED;

		audit_kadmind_unauth(rqstp->rq_xprt, l_port,
				    whoami,
				    "<null>", client_name);
		krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, whoami,
				"<null>", client_name, service_name,
				client_addr(rqstp, abuf));
		goto out;
	}

	kret = ulog_get_entries(handle->context, *arg, &ret);

	if (ret.ret == UPDATE_OK) {
		(void) snprintf(obuf, sizeof (obuf),
		gettext("%s; Incoming SerialNo=%u; Outgoing SerialNo=%u"),
				replystr(ret.ret),
				(ulong_t)arg->last_sno,
				(ulong_t)ret.lastentry.last_sno);
	} else {
		(void) snprintf(obuf, sizeof (obuf),
		gettext("%s; Incoming SerialNo=%u; Outgoing SerialNo=N/A"),
				replystr(ret.ret),
				(ulong_t)arg->last_sno);
	}

	audit_kadmind_auth(rqstp->rq_xprt, l_port,
			whoami,
			obuf, client_name, kret);

	krb5_klog_syslog(LOG_NOTICE, LOG_DONE, whoami,
			obuf,
			((kret == 0) ? "success" : error_message(kret)),
			client_name, service_name,
			client_addr(rqstp, abuf));

out:
	if (nofork)
		debprret(whoami, ret.ret, ret.lastentry.last_sno);
	if (client_name)
		free(client_name);
	if (service_name)
		free(service_name);
	if (name)
		gss_release_name(&min_stat, &name);
	return (&ret);
}
Example #26
0
char *alloc_sub_basic(const char *smb_name, const char *str)
{
	char *b, *p, *s, *t, *r, *a_string;
	fstring pidstr;
	struct passwd *pass;
	const char *local_machine_name = get_local_machine_name();

	/* workaround to prevent a crash while lookinf at bug #687 */
	
	if ( !str ) {
		DEBUG(0,("alloc_sub_basic: NULL source string!  This should not happen\n"));
		return NULL;
	}
	
	a_string = strdup(str);
	if (a_string == NULL) {
		DEBUG(0, ("alloc_sub_specified: Out of memory!\n"));
		return NULL;
	}
	
	for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {

		r = NULL;
		b = t = a_string;
		
		switch (*(p+1)) {
		case 'U' : 
			r = strdup_lower(smb_name);
			if (r == NULL) goto error;
			t = realloc_string_sub(t, "%U", r);
			break;
		case 'G' :
			r = strdup(smb_name);
			if (r == NULL) goto error;
			if ((pass = Get_Pwnam(r))!=NULL) {
				t = realloc_string_sub(t, "%G", gidtoname(pass->pw_gid));
			} 
			break;
		case 'D' :
			r = strdup_upper(current_user_info.domain);
			if (r == NULL) goto error;
			t = realloc_string_sub(t, "%D", r);
			break;
		case 'I' :
			t = realloc_string_sub(t, "%I", client_addr());
			break;
		case 'L' : 
			if (local_machine_name && *local_machine_name)
				t = realloc_string_sub(t, "%L", local_machine_name); 
			else
				t = realloc_string_sub(t, "%L", global_myname()); 
			break;
		case 'N':
			t = realloc_string_sub(t, "%N", automount_server(smb_name));
			break;
		case 'M' :
			t = realloc_string_sub(t, "%M", client_name());
			break;
		case 'R' :
			t = realloc_string_sub(t, "%R", remote_proto);
			break;
		case 'T' :
			t = realloc_string_sub(t, "%T", timestring(False));
			break;
		case 'a' :
			t = realloc_string_sub(t, "%a", remote_arch);
			break;
		case 'd' :
			slprintf(pidstr,sizeof(pidstr)-1, "%d",(int)sys_getpid());
			t = realloc_string_sub(t, "%d", pidstr);
			break;
		case 'h' :
			t = realloc_string_sub(t, "%h", myhostname());
			break;
		case 'm' :
			t = realloc_string_sub(t, "%m", remote_machine);
			break;
		case 'v' :
			t = realloc_string_sub(t, "%v", SAMBA_VERSION_STRING);
			break;
		case '$' :
			t = realloc_expand_env_var(t, p); /* Expand environment variables */
			break;
			
		default: 
			break;
		}

		p++;
		SAFE_FREE(r);
		if (t == NULL) goto error;
		a_string = t;
	}

	return a_string;
error:
	SAFE_FREE(a_string);
	return NULL;
}
Example #27
0
connection_struct *make_connection(struct smbd_server_connection *sconn,
				   const char *service_in, DATA_BLOB password,
				   const char *pdev, uint16 vuid,
				   NTSTATUS *status)
{
	uid_t euid;
	user_struct *vuser = NULL;
	fstring service;
	fstring dev;
	int snum = -1;
	char addr[INET6_ADDRSTRLEN];

	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;
	}

	if(lp_security() != SEC_SHARE) {
		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(lp_security() != SEC_SHARE) {
			DATA_BLOB no_pw = data_blob_null;
			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_snum(sconn,
						    vuser->homes_snum,
						    vuser, no_pw, 
						    dev, status);
		} else {
			/* Security = share. Try with
			 * current_user_info.smb_name as the username.  */
			if (*current_user_info.smb_name) {
				fstring unix_username;
				fstrcpy(unix_username,
					current_user_info.smb_name);
				map_username(sconn, unix_username);
				snum = find_service(unix_username);
			} 
			if (snum != -1) {
				DEBUG(5, ("making a connection to 'homes' "
					  "service %s based on "
					  "security=share\n", service_in));
				return make_connection_snum(sconn,
							    snum, NULL,
							    password,
							    dev, status);
			}
		}
	} else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
		   && strequal(service_in,
			       lp_servicename(vuser->homes_snum))) {
		DATA_BLOB no_pw = data_blob_null;
		DEBUG(5, ("making a connection to 'homes' service [%s] "
			  "created at session setup time\n", service_in));
		return make_connection_snum(sconn,
					    vuser->homes_snum,
					    vuser, no_pw, 
					    dev, status);
	}
	
	fstrcpy(service, service_in);

	strlower_m(service);

	snum = find_service(service);

	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(),
			client_addr(get_client_fd(),addr,sizeof(addr)),
			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(snum) != '\0'))  {
		DEBUG(3, ("refusing connection to dfs proxy share '%s' "
			  "(pointing to %s)\n", 
			service, lp_msdfs_proxy(snum)));
		*status = NT_STATUS_BAD_NETWORK_NAME;
		return NULL;
	}

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

	return make_connection_snum(sconn, snum, vuser,
				    password,
				    dev, status);
}
Example #28
0
static int rsync_module(int fd, int i)
{
	int argc=0;
	char *argv[MAX_ARGS];
	char **argp;
	char line[MAXPATHLEN];
	uid_t uid = (uid_t)-2;
	gid_t gid = (gid_t)-2;
	char *p;
	char *addr = client_addr(fd);
	char *host = client_name(fd);
	char *name = lp_name(i);
	int use_chroot = lp_use_chroot(i);
	int start_glob=0;
	int ret;
	char *request=NULL;
	extern int am_sender;
	extern int remote_version;
	extern int am_root;

	if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
		rprintf(FERROR,"rsync denied on module %s from %s (%s)\n",
			name, client_name(fd), client_addr(fd));
		io_printf(fd,"@ERROR: access denied to %s from %s (%s)\n",
			  name, client_name(fd), client_addr(fd));
		return -1;
	}

	if (!claim_connection(lp_lock_file(i), lp_max_connections(i))) {
		if (errno) {
			rprintf(FERROR,"failed to open lock file %s : %s\n",
				lp_lock_file(i), strerror(errno));
			io_printf(fd,"@ERROR: failed to open lock file %s : %s\n",
				  lp_lock_file(i), strerror(errno));
		} else {
			rprintf(FERROR,"max connections (%d) reached\n",
				lp_max_connections(i));
			io_printf(fd,"@ERROR: max connections (%d) reached - try again later\n", lp_max_connections(i));
		}
		return -1;
	}

	
	auth_user = auth_server(fd, i, addr, "@RSYNCD: AUTHREQD ");

	if (!auth_user) {
		rprintf(FERROR,"auth failed on module %s from %s (%s)\n",
			name, client_name(fd), client_addr(fd));
		io_printf(fd,"@ERROR: auth failed on module %s\n",name);
		return -1;		
	}

	module_id = i;

	if (lp_read_only(i))
		read_only = 1;

	am_root = (getuid() == 0);

	if (am_root) {
		p = lp_uid(i);
		if (!name_to_uid(p, &uid)) {
			if (!isdigit(*p)) {
				rprintf(FERROR,"Invalid uid %s\n", p);
				io_printf(fd,"@ERROR: invalid uid\n");
				return -1;
			} 
			uid = atoi(p);
		}

		p = lp_gid(i);
		if (!name_to_gid(p, &gid)) {
			if (!isdigit(*p)) {
				rprintf(FERROR,"Invalid gid %s\n", p);
				io_printf(fd,"@ERROR: invalid gid\n");
				return -1;
			} 
			gid = atoi(p);
		}
	}

	p = lp_include_from(i);
	add_exclude_file(p, 1, 1);

	p = lp_include(i);
	add_include_line(p);

	p = lp_exclude_from(i);
	add_exclude_file(p, 1, 0);

	p = lp_exclude(i);
	add_exclude_line(p);

	log_open();

	if (use_chroot) {
		if (chroot(lp_path(i))) {
			rprintf(FERROR,"chroot %s failed\n", lp_path(i));
			io_printf(fd,"@ERROR: chroot failed\n");
			return -1;
		}

		if (!push_dir("/", 0)) {
			rprintf(FERROR,"chdir %s failed\n", lp_path(i));
			io_printf(fd,"@ERROR: chdir failed\n");
			return -1;
		}

	} else {
		if (!push_dir(lp_path(i), 0)) {
			rprintf(FERROR,"chdir %s failed\n", lp_path(i));
			io_printf(fd,"@ERROR: chdir failed\n");
			return -1;
		}
	}

	if (am_root) {
		if (setgid(gid)) {
			rprintf(FERROR,"setgid %d failed\n", gid);
			io_printf(fd,"@ERROR: setgid failed\n");
			return -1;
		}

		if (setuid(uid)) {
			rprintf(FERROR,"setuid %d failed\n", uid);
			io_printf(fd,"@ERROR: setuid failed\n");
			return -1;
		}

		am_root = (getuid() == 0);
	}

	io_printf(fd,"@RSYNCD: OK\n");

	argv[argc++] = "rsyncd";

	while (1) {
		if (!read_line(fd, line, sizeof(line)-1)) {
			return -1;
		}

		if (!*line) break;

		p = line;

		argv[argc] = strdup(p);
		if (!argv[argc]) {
			return -1;
		}

		if (start_glob) {
			if (start_glob == 1) {
				request = strdup(p);
				start_glob++;
			}
			glob_expand(name, argv, &argc, MAX_ARGS, !use_chroot);
		} else {
			argc++;
		}

		if (strcmp(line,".") == 0) {
			start_glob = 1;
		}

		if (argc == MAX_ARGS) {
			return -1;
		}
	}

	if (!use_chroot) {
		/*
		 * Note that this is applied to all parameters, whether or not
		 *    they are filenames, but no other legal parameters contain
		 *    the forms that need to be sanitized so it doesn't hurt;
		 *    it is not known at this point which parameters are files
		 *    and which aren't.
		 */
		for (i = 1; i < argc; i++) {
			sanitize_path(argv[i]);
		}
	}

	ret = parse_arguments(argc, argv, 0);

	if (request) {
		if (*auth_user) {
			rprintf(FINFO,"rsync %s %s from %[email protected]%s (%s)\n",
				am_sender?"on":"to",
				request, auth_user, host, addr);
		} else {
			rprintf(FINFO,"rsync %s %s from %s (%s)\n",
				am_sender?"on":"to",
				request, host, addr);
		}
		free(request);
	}

#if !TRIDGE
	/* don't allow the logs to be flooded too fast */
	if (verbose > 1) verbose = 1;
#endif

	argc -= optind;
	argp = argv + optind;
	optind = 0;

	if (remote_version > 17 && am_sender)
		io_start_multiplex_out(fd);

	if (!ret) {
		option_error();
	}

	if (lp_timeout(i)) {
		extern int io_timeout;
		io_timeout = lp_timeout(i);
	}

	start_server(fd, fd, argc, argp);

	return 0;
}
Example #29
0
/* A generic logging routine for send/recv, with parameter substitiution. */
static void log_formatted(enum logcode code, const char *format, const char *op,
			  struct file_struct *file, const char *fname, int iflags,
			  const char *hlink)
{
	char buf[MAXPATHLEN+1024], buf2[MAXPATHLEN], fmt[32];
	char *p, *s, *c;
	const char *n;
	size_t len, total;
	int64 b;

	*fmt = '%';

	/* We expand % codes one by one in place in buf.  We don't
	 * copy in the terminating null of the inserted strings, but
	 * rather keep going until we reach the null of the format. */
	total = strlcpy(buf, format, sizeof buf);
	if (total > MAXPATHLEN) {
		rprintf(FERROR, "log-format string is WAY too long!\n");
		exit_cleanup(RERR_MESSAGEIO);
	}
	buf[total++] = '\n';
	buf[total] = '\0';

	for (p = buf; (p = strchr(p, '%')) != NULL; ) {
		int humanize = 0;
		s = p++;
		c = fmt + 1;
		while (*p == '\'') {
			humanize++;
			p++;
		}
		if (*p == '-')
			*c++ = *p++;
		while (isDigit(p) && c - fmt < (int)(sizeof fmt) - 8)
			*c++ = *p++;
		while (*p == '\'') {
			humanize++;
			p++;
		}
		if (!*p)
			break;
		*c = '\0';
		n = NULL;

		/* Note for %h and %a: it doesn't matter what fd we pass to
		 * client_{name,addr} because rsync_module will already have
		 * forced the answer to be cached (assuming, of course, for %h
		 * that lp_reverse_lookup(module_id) is true). */
		switch (*p) {
		case 'h':
			if (am_daemon) {
				n = lp_reverse_lookup(module_id)
				  ? client_name(0) : undetermined_hostname;
			}
			break;
		case 'a':
			if (am_daemon)
				n = client_addr(0);
			break;
		case 'l':
			strlcat(fmt, "s", sizeof fmt);
			snprintf(buf2, sizeof buf2, fmt,
				 do_big_num(F_LENGTH(file), humanize, NULL));
			n = buf2;
			break;
		case 'U':
			strlcat(fmt, "u", sizeof fmt);
			snprintf(buf2, sizeof buf2, fmt,
				 uid_ndx ? F_OWNER(file) : 0);
			n = buf2;
			break;
		case 'G':
			if (!gid_ndx || file->flags & FLAG_SKIP_GROUP)
				n = "DEFAULT";
			else {
				strlcat(fmt, "u", sizeof fmt);
				snprintf(buf2, sizeof buf2, fmt,
					 F_GROUP(file));
				n = buf2;
			}
			break;
		case 'p':
			strlcat(fmt, "d", sizeof fmt);
			snprintf(buf2, sizeof buf2, fmt, (int)getpid());
			n = buf2;
			break;
		case 'M':
			n = c = timestring(file->modtime);
			while ((c = strchr(c, ' ')) != NULL)
				*c = '-';
			break;
		case 'B':
			c = buf2 + MAXPATHLEN - PERMSTRING_SIZE - 1;
			permstring(c, file->mode);
			n = c + 1; /* skip the type char */
			break;
		case 'o':
			n = op;
			break;
		case 'f':
			if (fname) {
				c = f_name_buf();
				strlcpy(c, fname, MAXPATHLEN);
			} else
				c = f_name(file, NULL);
			if (am_sender && F_PATHNAME(file)) {
				pathjoin(buf2, sizeof buf2,
					 F_PATHNAME(file), c);
				clean_fname(buf2, 0);
				if (fmt[1]) {
					strlcpy(c, buf2, MAXPATHLEN);
					n = c;
				} else
					n = buf2;
			} else if (am_daemon && *c != '/') {
				pathjoin(buf2, sizeof buf2,
					 curr_dir + module_dirlen, c);
				clean_fname(buf2, 0);
				if (fmt[1]) {
					strlcpy(c, buf2, MAXPATHLEN);
					n = c;
				} else
					n = buf2;
			} else {
				clean_fname(c, 0);
				n = c;
			}
			if (*n == '/')
				n++;
			break;
		case 'n':
			if (fname) {
				c = f_name_buf();
				strlcpy(c, fname, MAXPATHLEN);
			} else
				c = f_name(file, NULL);
			if (S_ISDIR(file->mode))
				strlcat(c, "/", MAXPATHLEN);
			n = c;
			break;
		case 'L':
			if (hlink && *hlink) {
				n = hlink;
				strlcpy(buf2, " => ", sizeof buf2);
			} else if (S_ISLNK(file->mode) && !fname) {
				n = F_SYMLINK(file);
				strlcpy(buf2, " -> ", sizeof buf2);
			} else {
				n = "";
				if (!fmt[1])
					break;
				strlcpy(buf2, "    ", sizeof buf2);
			}
			strlcat(fmt, "s", sizeof fmt);
			snprintf(buf2 + 4, sizeof buf2 - 4, fmt, n);
			n = buf2;
			break;
		case 'm':
			n = lp_name(module_id);
			break;
		case 't':
			n = timestring(time(NULL));
			break;
		case 'P':
			n = full_module_path;
			break;
		case 'u':
			n = auth_user;
			break;
		case 'b':
		case 'c':
			if (!(iflags & ITEM_TRANSFER))
				b = 0;
			else if ((!!am_sender) ^ (*p == 'c'))
				b = total_data_written - initial_data_written;
			else
				b = total_data_read - initial_data_read;
			strlcat(fmt, "s", sizeof fmt);
			snprintf(buf2, sizeof buf2, fmt,
				 do_big_num(b, humanize, NULL));
			n = buf2;
			break;
		case 'C':
			n = NULL;
			if (S_ISREG(file->mode)) {
				if (always_checksum && canonical_checksum(checksum_type))
					n = sum_as_hex(checksum_type, F_SUM(file));
				else if (iflags & ITEM_TRANSFER && canonical_checksum(xfersum_type))
					n = sum_as_hex(xfersum_type, sender_file_sum);
			}
			if (!n) {
				int checksum_len = csum_len_for_type(always_checksum ? checksum_type : xfersum_type);
				memset(buf2, ' ', checksum_len*2);
				buf2[checksum_len*2] = '\0';
				n = buf2;
			}
			break;
		case 'i':
			if (iflags & ITEM_DELETED) {
				n = "*deleting  ";
				break;
			}
			n  = c = buf2 + MAXPATHLEN - 32;
			c[0] = iflags & ITEM_LOCAL_CHANGE
			      ? iflags & ITEM_XNAME_FOLLOWS ? 'h' : 'c'
			     : !(iflags & ITEM_TRANSFER) ? '.'
			     : !local_server && *op == 's' ? '<' : '>';
			if (S_ISLNK(file->mode)) {
				c[1] = 'L';
				c[3] = '.';
				c[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
				     : !preserve_times || !receiver_symlink_times
				    || (iflags & ITEM_REPORT_TIMEFAIL) ? 'T' : 't';
			} else {
				c[1] = S_ISDIR(file->mode) ? 'd'
				     : IS_SPECIAL(file->mode) ? 'S'
				     : IS_DEVICE(file->mode) ? 'D' : 'f';
				c[3] = !(iflags & ITEM_REPORT_SIZE) ? '.' : 's';
				c[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
				     : !preserve_times ? 'T' : 't';
			}
			c[2] = !(iflags & ITEM_REPORT_CHANGE) ? '.' : 'c';
			c[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
			c[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
			c[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
			c[8] = !(iflags & ITEM_REPORT_ATIME) ? '.' : 'u';
			c[9] = !(iflags & ITEM_REPORT_ACL) ? '.' : 'a';
			c[10] = !(iflags & ITEM_REPORT_XATTR) ? '.' : 'x';
			c[11] = '\0';

			if (iflags & (ITEM_IS_NEW|ITEM_MISSING_DATA)) {
				char ch = iflags & ITEM_IS_NEW ? '+' : '?';
				int i;
				for (i = 2; c[i]; i++)
					c[i] = ch;
			} else if (c[0] == '.' || c[0] == 'h' || c[0] == 'c') {
				int i;
				for (i = 2; c[i]; i++) {
					if (c[i] != '.')
						break;
				}
				if (!c[i]) {
					for (i = 2; c[i]; i++)
						c[i] = ' ';
				}
			}
			break;
		}

		/* "n" is the string to be inserted in place of this % code. */
		if (!n)
			continue;
		if (n != buf2 && fmt[1]) {
			strlcat(fmt, "s", sizeof fmt);
			snprintf(buf2, sizeof buf2, fmt, n);
			n = buf2;
		}
		len = strlen(n);

		/* Subtract the length of the escape from the string's size. */
		total -= p - s + 1;

		if (len + total >= (size_t)sizeof buf) {
			rprintf(FERROR,
				"buffer overflow expanding %%%c -- exiting\n",
				p[0]);
			exit_cleanup(RERR_MESSAGEIO);
		}

		/* Shuffle the rest of the string along to make space for n */
		if (len != (size_t)(p - s + 1))
			memmove(s + len, p + 1, total - (s - buf) + 1);
		total += len;

		/* Insert the contents of string "n", but NOT its null. */
		if (len)
			memcpy(s, n, len);

		/* Skip over inserted string; continue looking */
		p = s + len;
	}

	rwrite(code, buf, total, 0);
}
Example #30
0
/* Callback from GSSRPC for garbled/forged/replayed/etc messages. */
static void
log_badverf(gss_name_t client_name, gss_name_t server_name,
            struct svc_req *rqst, struct rpc_msg *msg, char *data)
{
    static const struct {
        rpcproc_t proc;
        const char *proc_name;
    } proc_names[] = {
        {1, "CREATE_PRINCIPAL"},
        {2, "DELETE_PRINCIPAL"},
        {3, "MODIFY_PRINCIPAL"},
        {4, "RENAME_PRINCIPAL"},
        {5, "GET_PRINCIPAL"},
        {6, "CHPASS_PRINCIPAL"},
        {7, "CHRAND_PRINCIPAL"},
        {8, "CREATE_POLICY"},
        {9, "DELETE_POLICY"},
        {10, "MODIFY_POLICY"},
        {11, "GET_POLICY"},
        {12, "GET_PRIVS"},
        {13, "INIT"},
        {14, "GET_PRINCS"},
        {15, "GET_POLS"},
        {16, "SETKEY_PRINCIPAL"},
        {17, "SETV4KEY_PRINCIPAL"},
        {18, "CREATE_PRINCIPAL3"},
        {19, "CHPASS_PRINCIPAL3"},
        {20, "CHRAND_PRINCIPAL3"},
        {21, "SETKEY_PRINCIPAL3"},
        {22, "PURGEKEYS"},
        {23, "GET_STRINGS"},
        {24, "SET_STRING"}
    };
    OM_uint32 minor;
    gss_buffer_desc client, server;
    gss_OID gss_type;
    const char *a;
    rpcproc_t proc;
    unsigned int i;
    const char *procname;
    size_t clen, slen;
    char *cdots, *sdots;

    client.length = 0;
    client.value = NULL;
    server.length = 0;
    server.value = NULL;

    (void)gss_display_name(&minor, client_name, &client, &gss_type);
    (void)gss_display_name(&minor, server_name, &server, &gss_type);
    if (client.value == NULL) {
        client.value = "(null)";
        clen = sizeof("(null)") - 1;
    } else {
        clen = client.length;
    }
    trunc_name(&clen, &cdots);
    if (server.value == NULL) {
        server.value = "(null)";
        slen = sizeof("(null)") - 1;
    } else {
        slen = server.length;
    }
    trunc_name(&slen, &sdots);
    a = client_addr(rqst->rq_xprt);

    proc = msg->rm_call.cb_proc;
    procname = NULL;
    for (i = 0; i < sizeof(proc_names) / sizeof(*proc_names); i++) {
        if (proc_names[i].proc == proc) {
            procname = proc_names[i].proc_name;
            break;
        }
    }
    if (procname != NULL) {
        krb5_klog_syslog(LOG_NOTICE,
                         _("WARNING! Forged/garbled request: %s, claimed "
                           "client = %.*s%s, server = %.*s%s, addr = %s"),
                         procname, (int)clen, (char *)client.value, cdots,
                         (int)slen, (char *)server.value, sdots, a);
    } else {
        krb5_klog_syslog(LOG_NOTICE,
                         _("WARNING! Forged/garbled request: %d, claimed "
                           "client = %.*s%s, server = %.*s%s, addr = %s"),
                         proc, (int)clen, (char *)client.value, cdots,
                         (int)slen, (char *)server.value, sdots, a);
    }

    (void)gss_release_buffer(&minor, &client);
    (void)gss_release_buffer(&minor, &server);
}