Example #1
0
void    smtpd_peer_init(SMTPD_STATE *state)
{
    struct sockaddr_in sin;
    SOCKADDR_SIZE len = sizeof(sin);
    struct hostent *hp;
    int     i;

    /*
     * Avoid suprious complaints from Purify on Solaris.
     */
    memset((char *) &sin, 0, len);

    /*
     * Look up the peer address information.
     */
    if (getpeername(vstream_fileno(state->client),
		    (struct sockaddr *) & sin, &len) >= 0) {
	errno = 0;
    }

    /*
     * If peer went away, give up.
     */
    if (errno == ECONNRESET || errno == ECONNABORTED) {
	state->name = mystrdup(CLIENT_NAME_UNKNOWN);
	state->addr = mystrdup(CLIENT_ADDR_UNKNOWN);
	state->peer_code = SMTPD_PEER_CODE_PERM;
    }

    /*
     * Look up and "verify" the client hostname.
     */
    else if (errno == 0 && sin.sin_family == AF_INET) {
	state->addr = mystrdup(inet_ntoa(sin.sin_addr));
	hp = gethostbyaddr((char *) &(sin.sin_addr),
			   sizeof(sin.sin_addr), AF_INET);
	if (hp == 0) {
	    state->name = mystrdup(CLIENT_NAME_UNKNOWN);
	    state->peer_code = (h_errno == TRY_AGAIN ?
				SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM);
	} else if (valid_hostaddr(hp->h_name, DONT_GRIPE)) {
	    msg_warn("numeric result %s in address->name lookup for %s",
		     hp->h_name, state->addr);
	    state->name = mystrdup(CLIENT_NAME_UNKNOWN);
	    state->peer_code = SMTPD_PEER_CODE_PERM;
	} else if (!valid_hostname(hp->h_name, DONT_GRIPE)) {
	    state->name = mystrdup(CLIENT_NAME_UNKNOWN);
	    state->peer_code = SMTPD_PEER_CODE_PERM;
	} else {
	    state->name = mystrdup(hp->h_name);	/* hp->name is clobbered!! */
	    state->peer_code = SMTPD_PEER_CODE_OK;

	    /*
	     * Reject the hostname if it does not list the peer address.
	     */
#define REJECT_PEER_NAME(state, code) { \
	myfree(state->name); \
	state->name = mystrdup(CLIENT_NAME_UNKNOWN); \
	state->peer_code = code; \
    }

	    hp = gethostbyname(state->name);	/* clobbers hp->name!! */
	    if (hp == 0) {
		msg_warn("%s: hostname %s verification failed: %s",
			 state->addr, state->name, HSTRERROR(h_errno));
		REJECT_PEER_NAME(state, (h_errno == TRY_AGAIN ?
			      SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM));
	    } else if (hp->h_length != sizeof(sin.sin_addr)) {
		msg_warn("%s: hostname %s verification failed: bad address size %d",
			 state->addr, state->name, hp->h_length);
		REJECT_PEER_NAME(state, SMTPD_PEER_CODE_PERM);
	    } else {
		for (i = 0; /* void */ ; i++) {
		    if (hp->h_addr_list[i] == 0) {
			msg_warn("%s: address not listed for hostname %s",
				 state->addr, state->name);
			REJECT_PEER_NAME(state, SMTPD_PEER_CODE_PERM);
			break;
		    }
		    if (memcmp(hp->h_addr_list[i],
			       (char *) &sin.sin_addr,
			       sizeof(sin.sin_addr)) == 0)
			break;			/* keep peer name */
		}
	    }
	}
    }

    /*
     * If it's not Internet, assume the client is local, and avoid using the
     * naming service because that can hang when the machine is disconnected.
     */
    else {
	state->name = mystrdup("localhost");
	state->addr = mystrdup("127.0.0.1");	/* XXX bogus. */
	state->peer_code = SMTPD_PEER_CODE_OK;
    }

    /*
     * Do the name[addr] formatting for pretty reports.
     */
    state->namaddr =
	concatenate(state->name, "[", state->addr, "]", (char *) 0);
}
Example #2
0
int ldap_pvt_get_hname(
	const struct sockaddr *sa,
	int len,
	char *name,
	int namelen,
	char **err )
{
	int rc;
#if defined( HAVE_GETNAMEINFO )

#if defined( LDAP_R_COMPILE )
	ldap_pvt_thread_mutex_lock( &ldap_int_resolv_mutex );
#endif
	rc = getnameinfo( sa, len, name, namelen, NULL, 0, 0 );
#if defined( LDAP_R_COMPILE )
	ldap_pvt_thread_mutex_unlock( &ldap_int_resolv_mutex );
#endif
	if ( rc ) *err = (char *)AC_GAI_STRERROR( rc );
	return rc;

#else /* !HAVE_GETNAMEINFO */
	char *addr;
	int alen;
	struct hostent *hp = NULL;
#ifdef HAVE_GETHOSTBYADDR_R
	struct hostent hb;
	int buflen=BUFSTART, h_errno;
	char *buf=NULL;
#endif

#ifdef LDAP_PF_INET6
	if (sa->sa_family == AF_INET6) {
		struct sockaddr_in6 *sin = (struct sockaddr_in6 *)sa;
		addr = (char *)&sin->sin6_addr;
		alen = sizeof(sin->sin6_addr);
	} else
#endif
	if (sa->sa_family == AF_INET) {
		struct sockaddr_in *sin = (struct sockaddr_in *)sa;
		addr = (char *)&sin->sin_addr;
		alen = sizeof(sin->sin_addr);
	} else {
		rc = NO_RECOVERY;
		*err = (char *)HSTRERROR( rc );
		return rc;
	}
#if defined( HAVE_GETHOSTBYADDR_R )
	for(;buflen<BUFMAX;) {
		if (safe_realloc( &buf, buflen )==NULL) {
			*err = (char *)STRERROR( ENOMEM );
			return ENOMEM;
		}
#if (GETHOSTBYADDR_R_NARGS < 8)
		hp=gethostbyaddr_r( addr, alen, sa->sa_family,
			&hb, buf, buflen, &h_errno );
		rc = (hp == NULL) ? -1 : 0;
#else
		rc = gethostbyaddr_r( addr, alen, sa->sa_family,
			&hb, buf, buflen, 
			&hp, &h_errno );
#endif
#ifdef NETDB_INTERNAL
		if ((rc<0) &&
			(h_errno==NETDB_INTERNAL) &&
			(errno==ERANGE))
		{
			buflen*=2;
			continue;
		}
#endif
		break;
	}
	if (hp) {
		strncpy( name, hp->h_name, namelen );
	} else {
		*err = (char *)HSTRERROR( h_errno );
	}
	LDAP_FREE(buf);
#else /* HAVE_GETHOSTBYADDR_R */

#if defined( LDAP_R_COMPILE )
	ldap_pvt_thread_mutex_lock( &ldap_int_resolv_mutex );
#endif
	hp = gethostbyaddr( addr, alen, sa->sa_family );
	if (hp) {
		strncpy( name, hp->h_name, namelen );
		rc = 0;
	} else {
		rc = h_errno;
		*err = (char *)HSTRERROR( h_errno );
	}
#if defined( LDAP_R_COMPILE )
	ldap_pvt_thread_mutex_unlock( &ldap_int_resolv_mutex );
#endif

#endif	/* !HAVE_GETHOSTBYADDR_R */
	return rc;
#endif	/* !HAVE_GETNAMEINFO */
}