/*
 * bootparamd
 *
 * This plugin is distributed under the GPL
 */


#include <includes.h>
#ifdef HAVE_RPC_RPC_H
#include <rpc/rpc.h>
#include <rpcsvc/bootparam_prot.h>
#include <rpc/pmap_clnt.h>
#endif

#define BOOTPARAM_RPC 100026


#define NAME "Bootparamd gives NIS domain"
#define DESC "\
When  a  diskless  client  needs  to  boot,  it uses the bootparam\n\
protocol to get the necessary information needed from the  server.\n\
If bootparamd is running one can guess at which is the client  and\n\
server  or  use  a  program  such as bootparam_prot.x to determine\n\
which is which.\n\
\n\
If an intruder uses BOOTPARAMPROC_WHOAMI and provides the  address\n\
of  the  client,  he  will  get  it's  NIS  domain  name back from\n\
bootparamd.  If you know the  NIS domain name, it may be  possible\n\
to get a copy of the password file.\n\
One solution would be to filter incoming connections to port 111\n\
(portmap)\n\
This plugin will attempt to retrieve the NIS domain name by giving\n\
to the remote bootparamd some computer names\n\
Risk factor : High"

#define SUMMARY "attempts to retrieve the NIS domain name via bootparam"
#define COPYRIGHT "no copyright"
char * get_nis_domain(struct arglist * , char *);


PlugExport int plugin_init(struct arglist * desc);
PlugExport int plugin_init(struct arglist * desc)
{
  plug_set_name(desc, NAME);
  plug_set_description(desc, DESC);
  plug_set_summary(desc, SUMMARY);
  plug_set_copyright(desc, COPYRIGHT);
  plug_set_category(desc, ACT_ATTACK);
  plug_set_family(desc, "NIS");
  plug_set_timeout(desc, 50);
  return(0);
}



PlugExport int plugin_run(struct arglist * env);
PlugExport int plugin_run(struct arglist * env)
{
 if(plug_get_key(env, "rpc/portmapper")&&
     (strlen(plug_get_key(env, "rpc/portmapper"))<3))return(0);
 if (callrpc (plug_get_hostname(env), BOOTPARAM_RPC, -1, 0,
		       (xdrproc_t) xdr_void, (caddr_t) NULL,
		       (xdrproc_t) xdr_void, (caddr_t) NULL) == 9)
 {
  int port;
  int found = 0;
  char * domain = NULL;
  struct arglist * hosts = plug_get_key(env, "hosts");
  port = getrpcport(plug_get_hostname(env), BOOTPARAM_RPC, 1,IPPROTO_UDP);
  if(!port)port = -1;
  while(hosts && hosts->next && !found)
  {
   if((domain=get_nis_domain(env, hosts->name)))found = 1;
   hosts = hosts->next;
  }
  
  if(found)
  {
   char * report = emalloc(1024+strlen(domain));
   if(((int)plug_get_key(env, "nis/domain"))==-1)
    plug_set_key(env,"nis/domain", ARG_STRING, domain);
   sprintf(report, "\
The remote bootparamd gave out the \n\
remote NIS domain name which is \n\%s\n\
Solution : disable bootparamd or filter\n\
incoming connections to port 111", domain);
   post_hole_udp(env, port, report);
   efree(&report);
  }
  return(0);
 }
    
 return(0);
}



char * get_nis_domain(env, client)
 struct arglist * env;
 char * client;
{
  long hostip;
  struct hostent *hp;
  bp_whoami_arg w_arg;
  bp_whoami_res w_res;
  struct in_addr a;
  extern void timeout();
  enum clnt_stat errcode;

  a = nn_resolve(client);
  bcopy(&a, &w_arg.client_address.bp_address_u.ip_addr,
  	sizeof(struct in_addr));
  w_arg.client_address.address_type = IP_ADDR_TYPE;
  bzero((caddr_t) &w_res, sizeof(bp_whoami_res));
  errcode = callrpc(plug_get_hostname(env), BOOTPARAMPROG, BOOTPARAMVERS,
                BOOTPARAMPROC_WHOAMI, NULL/*xdr_bp_whoami_arg*/, &w_arg,
                NULL/*xdr_bp_whoami_res*/, &w_res);
  if (errcode == RPC_SUCCESS)return(w_res.domain_name);
  else return(NULL);
}
      
