pam_access认证模块 :该模块提供基于username、hostname、ip address以及tty的访问控制。默认该模块的配置文件是/etc/security/access.conf。
这里介绍IP地址匹配函数的开发代码
//isipaddr-查明所提供的字符串是否为IP地址
static int isipaddr(const char *string,int *addr_type,struct sockaddr_storage *addr)
{
struct sockaddr_storage local_addr;
int is_ip;
//我们使用struct sockaddr_storage addr,因为struct in_addr/in6_addr是struct sockaddr不可分割的一部分,我们不想使用它的值
if(addr == NULL)
addr = &local_addr;
memest(addr, 0, sizeof(struct socker_storage));
//ipv4
if(inet_pton(AF_INET,string,addr) > 0)
{
if(addr_type != NULL)
*addr_type = AF_INET;
is_ip = YES;
}
//ipv6
else if(inet_pton(AF_INET6,string,addr) > 0)
{
if(addr_type != NULL)
*addr_type = AF_INET6;
is_ip = YES;
}
else
is_ip = 0;
return is_ip;
}
//are_addresses_equal-将IP地址字符串转换为实际IP地址,并对它们进行比较,以确定它们是否相等。如果提供了网络掩码,它将用于将比较聚焦到相关位。
static int are_addresses_equal(const char *ipaddr0, const char *ipaddr1, const char *netmask)
{
struct sockaddr_storage addr0;
struct sockaddr_storage addr1;
int addr_type0 = 0;
int addr_type1 = 0;
if(isipaddr(ipaddr0, &addr_type, &addr0) == NO)
return NO;
if(isipaddr(ipaddr1, &addr_type, &addr1) == NO)
return NO;
if(addr_type0 != addr_type1) //不同的地址类别
return NO;
if(netmask != NULL) //得到了网掩码,说明地址正常
{
struct sockaddr_storage nmask;
unsigned char *byte_a, *byte_nm;
memset(&nmask, 0, sizeof(struct sockaddr_storage));
if(inet_pton(addr_type0, netmask, (void *)&nmask) > 0)
{
unsigned int i;
byte_a = (unsigned char *)(&addr0);
byte_nm = (unsigned char *)(&nmask);
for(i=0;i<sizeof(struct sockaddr_storage);i++){
byte_a[i] = byte_a[i] & byte_nm[i];
}
byte_a = (unsigned char *)(&addr1);
byte_nm = (unsigned char *)(&nmask);
for(i=0;i<sizeof(struct sockaddr_storage);i++){
byte_a[i] = byte_a[i] & byte_nm[i];
}
}
}
//判断两个地址是否相等
if(memcmp((void *)&addr0,(void *)&addr1,sizeof(struct sockaddr_storage)) == 0)
{
return YES;
}
return NO;
}
static char *number_to_netmask(long netmask, int addr_type,char *ipaddr_buf, size_t ipaddr_buf_len)
{
//我们使用struct sockaddr_storage addr,因为struct in_addr/in6_addr是struct sockaddr不可分割的一部分,我们不想使用它的值
struct sockaddr_storage nmask;
unsigned char *byte_nm;
const char *ipaddr_dst = NULL;
int i,ip_bytes;
if(netmask = 0) //mask为0等同于没有
{
return(NULL);
}
memset(&nmask, 0, sizeof(struct sockaddr_storage));
if(addr_type == AF_INET6)
{ //ipv6掩码地址
ip_bytes = 16;
}
else
{ //默认可能是ipv4地址掩码
addr_type = AF_INET;
ip_bytes = 4;
}
byte_nm = (unsigned char *)(&nmask);
//将数字转换为掩码
for(i=0;i<ip_bytes;i++)
{
if(netmask >= 8)
{
byte_nm[i] = 0xff;
netmask -= 8;
}
else if(netmask > 0)
{
byte_nm[i] = 0xff << (8 - netmask);
break;
}
else if(netmask <= 0){
break;
}
}
//现在生成网络掩码地址字符串
ipaddr_dst = inet_ntop(addr_type, &nmask, ipaddr_buf, ipaddr_buf_len);
if(ipaddr_dst == ipaddr_buf){
return(ipaddr_buf);
}
return(NULL);
}
//network_netmask_match-将字符串与一个令牌匹配,其中字符串是主机名或ip地址,tok表示单个ip地址或网络
static int network_netmask_match(pam_handle_t *pamh,const char *tok,const char *string,struct login_info *item)
{
char *netmask_ptr;
char netmask_string[MAXHOSTNAMELEN + 1];
int addr_type;
if(item->debug)
pam_syslog(pamh,LOG_DEBUG,"network_netmask_match: tok=%s,item=%s",tok,string);
//检查tok是否是地址类型
if(netmask_ptr = strchr(tok,'/') != NULL)
{
long netmask = 0;
//YES
*netmask_ptr = 0;
netmask_ptr++;
if(isipaddr(tok,&addr_type,NULL) == NO)
{
return NO; //没有网址
}
//检查网络掩码
if(isipaddr(netmask_ptr,NULL,NULL) == N0)
{ //网络掩码作为整数值
char *endptr = NULL;
netmask = strtol(netmask_ptr,&endptr,0);
if((endptr == NULL)||(*endptr !='\0'))
{ //无效的网络掩码值
return NO;
}
if((netmask < 0)||(netmask >= 128))
{ //网络掩码值超出范围
return NO;
}
netmask_ptr = number_to_netmask(netmask, addr_type, netmask_string, MAXHOSTNAMELEN);
}
}
else
//然后检查它是否只是一个地址
if(isipaddr(tok, NULL, NULL) != YES)
{
return NO;
}
if(isipaddr(string,NULL,NULL) != YES)
{
//假设他们都有一个主机名
struct addrinfo hint;
memset(&hint, '\0', sizeof(hint));
hint.ai_flags = AI_CANONNAME;
hint.ai_family = AI_UNSPEC;
if(item->gai_rv != 0)
return NO;
else if(!item->res &&(item->gai_rv = getaddrinfo(string, NULL, &hint, &item->res)) != 0)
return NO;
else
{
struct addrinfo *runp = item->res;
while(runp != NULL)
{
char buf[INET6_ADDRSTRLEN];
inet_ntop(runp->ai_family, run->ai_family == AF_INET?(void *)&((struct sockaddr_in *)runp->ai_addr)->sin_addr:(void *)&((struct sockaddr_in6 *)runp->ai_addr)->sin6_addr,buf,sizeof(buf));
if(are_addresses_equal(buf,tok,netmask_ptr))
{
return YES;
}
rump = runp->ai_next;
}
}
}
else
return(are_addresses_equal(string,tok,netmask_ptr));
return NO;
}
1037

被折叠的 条评论
为什么被折叠?



