#include #include #include #include #include #include "dnsconf.h" #include "dnsconf.m" #include "internal.h" static DNSCONF_HELP_FILE help_acl ("acl"); PUBLIC ADDRESS_MATCH::ADDRESS_MATCH () { } PUBLIC ADDRESS_MATCH::ADDRESS_MATCH ( const char *_ip, // IP or acl name const char *comment) { name.setfrom (_ip); name.setcomment (comment); } PUBLIC ADDRESS_MATCH::ADDRESS_MATCH ( const char *_ip, const char *_netsize, const char *comment) { name.setfrom (_ip); name.setcomment (comment); netsize.setfrom (_netsize); } PUBLIC int ADDRESS_MATCH::edit (const ACLS &acls) { int ret = -1; DIALOG dia; dia.newf_str (MSG_U(F_NETHOSTACL,"Network, Host or ACL"),name); dia.last_noempty(); dia.newf_str (MSG_U(F_NETSIZE,"Network type (/xx)"),netsize); dia.delwhat (MSG_U(I_DELADDR,"Select [Del] to delete this entry")); int nof = 0; while (1){ MENU_STATUS code = dia.edit (MSG_U(T_ADDRMATCH,"One address match") ,MSG_U(I_ADDRMATCH ,"You must enter here one of the following combination\n" " One host IP number\n" " A network IP number and a number of signigficative bits\n" " (16 for a class B, 24 for a class C network)\n" " One ACL name\n") ,help_acl ,nof,MENUBUT_ACCEPT|MENUBUT_DEL|MENUBUT_CANCEL); if (code == MENU_CANCEL || code == MENU_ESCAPE){ dia.restore(); break; }else if (code == MENU_DEL){ ret = 1; break; }else{ bool err = false; const char *ip = name.get(); nof = 0; // If any error, this will be the next // edit field, unless the error is in the netsize if (netsize.is_empty()){ // Only an ACL or a host ip number here if (isdigit(ip[0])){ if (!ipnum_validip (ip,true)){ xconf_error (MSG_U(E_HOSTIP ,"You must enter a host IP number here")); err = true; } }else if (!acls.exist(ip)){ xconf_error (MSG_U(E_IVLDACL,"%s is not valid ACL name") ,ip); err = true; } }else{ // The IP number is either a normal network or a subnet // so ipnum_validip can't tell if (!ipnum_validip (ip,false)){ xconf_error (MSG_U(E_NETWORKIP ,"You must enter a network IP number here")); err = true; }else{ int size = netsize.getval(); if (size<1 || size > 32){ xconf_error (MSG_U(E_NETSIZE ,"You must provide a number between\n" "1 and 32")); err = true; nof = 1; } } } if (!err){ ret = 0; break; } } } return ret; } PUBLIC void ADDRESS_MATCH::write (FILE_CFG *fout) { if (!name.comment.is_empty()) fprintf (fout,"\t%s\n",name.comment.get()); if (!name.is_empty()){ fprintf (fout,"\t%s",name.get()); if (!netsize.is_empty()){ fprintf (fout,"/%s",netsize.get()); } fprintf (fout,";\n"); } } PUBLIC bool ADDRESS_MATCH::is_empty() { return name.is_empty() && netsize.is_empty(); } PUBLIC bool ADDRESS_MATCH::is_none() { return name.icmp("none")==0; } PUBLIC bool ADDRESS_MATCH::is_any() { return name.icmp("any")==0; } PUBLIC bool ADDRESS_MATCH::is_localnet() { return name.icmp("localnet")==0; } PUBLIC ADDRESS_MATCH * ACL::getitem(int no) const { return (ADDRESS_MATCH *)ARRAY::getitem(no); } // true if val=1 and contain none // true if val=2 and contain any PUBLIC bool ACL::is_empty(int val) const { int count=0; for (int i=0; iis_empty())) count++; if (val==1 && getitem(i)->is_none()) return true; if (val==2 && getitem(i)->is_any()) return true; } return count == 0; } PUBLIC ACL::ACL(const char *_name) { name.setfrom (_name); }; PUBLIC void ACL::write (FILE_CFG *fout) { fprintf (fout,"acl %s{\n",name.get()); for (int i=0; iwrite (fout); } fprintf (fout,"};\n"); } PUBLIC ACL * ACLS::getitem(int no) const { return (ACL *)ARRAY::getitem(no); } PUBLIC void ACLS::write (FILE_CFG *fout) { for (int i=0; iwrite(fout); } PUBLIC int ACL::editname() { int ret = -1; DIALOG dia; dia.newf_str (MSG_U(F_ACLNAME,"Name"),name); dia.last_noempty(); int nof = 0; while (1){ MENU_STATUS code = dia.edit (MSG_U(T_ACLNAME,"Acl name") ,MSG_U(I_ACLNAME,"Enter the name of the acl which will be\n" "used in access control") ,help_acl ,nof); if (code == MENU_CANCEL || code == MENU_ESCAPE){ dia.restore(); break; }else{ const char *pt = name.get(); while (*pt != '\0'){ if (isspace(*pt)){ break; } pt++; } if (*pt != '\0'){ xconf_error (MSG_U(E_NOSPACE ,"You must enter a single word.\n" "No space allowed!")); }else{ ret = 0; break; } } } return ret; } PUBLIC int ACL::edit(DNS &dns, const ACLS &acls) { int ret = 0; if (name.is_empty()){ if (editname() == 0) dns.write(); } if (name.is_empty()) return -1; DIALOG_RECORDS dia; dia.newf_head ("",MSG_U(H_ACL,"Host/Network/Acl\tNet size")); dia.addwhat (MSG_U(I_ADDMATCH,"Select [Add] to add a new access pattern")); dia.delwhat (MSG_U(I_DELACL,"Select [Del] to delete this")); dia.setbutinfo (MENU_USR1,MSG_U(B_EDITNAME,"Edit acl name") ,MSG_R(B_EDITNAME)); int nof = 0; while (1){ for (int i=0; iname.get(),m->netsize.get()); } dia.remove_last(getnb()+1); char title[100]; snprintf (title,sizeof(title)-1,MSG_U(T_ACL,"Access control list %s") ,name.get()); MENU_STATUS code = dia.editmenu (title ,"",help_acl,nof,MENUBUT_USR1); if (code == MENU_ESCAPE || code == MENU_QUIT){ break; }else if (code == MENU_USR1){ if (editname()==0) dns.write(); }else if (code == MENU_DEL){ if (xconf_delok()){ ret = 1; break; } }else if (code == MENU_ADD){ ADDRESS_MATCH *m = new ADDRESS_MATCH; int ok = m->edit(acls); if (ok == 0){ add (m); dns.write(); }else{ delete m; } }else if (nof >=0 && nof edit(acls); if (ok != -1){ if (ok == 1) remove_del (m); dns.write(); } } } return ret; } PUBLIC int ACLS::edit(DNS &dns) { DIALOG_RECORDS dia; dia.addwhat (MSG_U(I_ADDACL,"Select [Add] to add a new access control list")); dia.newf_head ("",MSG_U(H_ACLS,"Acl names")); int nof = 0; while (1){ for (int i=0; iname.get(),""); } dia.remove_last (getnb()+1); MENU_STATUS code = dia.editmenu (MSG_U(T_ACLS,"Access control lists") ,"",help_acl,nof,0); if (code == MENU_ESCAPE || code == MENU_QUIT){ break; }else if (code == MENU_ADD){ ACL *ac = new ACL(""); add (ac); int ok = ac->edit(dns,*this); if (ok != 0){ remove_del(ac); }else{ dns.write(); } }else if (nof >=0 && nof edit(dns,*this); if (ok != -1){ if (ok == 1) remove_del(ac); dns.write(); } } } return 0; } /* Locate an ACL in the list */ PUBLIC int ACLS::locate (const char *name) const { int ret = -1; for (int i=0; iname.cmp(name)==0){ ret = i; break; } } return ret; } /* Return true if an ACL exists. Check for builtin ones. */ PUBLIC bool ACLS::exist (const char *name) const { return strcmp(name,"none")==0 || strcmp(name,"any")==0 || strcmp(name,"localhost")==0 || strcmp(name,"localnets")==0 || locate(name)!=-1; }