QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 917|回复: 14

网络编程问题

[复制链接]
发表于 2004-3-16 23:52:54 | 显示全部楼层 |阅读模式
linux redhat 7.2下
--------------------------------------------------------------------------------

在/home/myname/下,我写了一个原始插口的程序,其中用到
setuid(getuid());
然后gcc -o my my.c 编译通过,在
root下
chown root my
chmod +s my
------------
这根本改变不了my的权限------"socket failed,操作不允许",
真头痛.请问是什么原因呢?有什么好办法?
我本意是要以普通用户,执行超级用户才能执行的程序.
发表于 2004-3-17 18:10:48 | 显示全部楼层
首先,chown仅仅改变了文件的所有者。谁执行这个程序,那么进程的UID就是谁的UID
回复

使用道具 举报

发表于 2004-3-17 18:42:38 | 显示全部楼层
我再补充一句:无论如何,你不能以普通用户的身份执行特权指令,如果行,那root身份不是就没用了!对于你所用的命令,可以参见《unix环境高级编程》4.4和8.10小节。
回复

使用道具 举报

 楼主| 发表于 2004-3-17 22:43:36 | 显示全部楼层
首先,chown仅仅改变了文件的所有者。谁执行这个程序,那么进程的UID就是谁的UID

请讲详细点儿行不?我还不太清楚.
我再补充一句:无论如何,你不能以普通用户的身份执行特权指令,如果行,那root身份不是就没用了!对于你所用的命令,可以参见《unix环境高级编程》4.4和8.10小节。

真可惜,我没有《unix环境高级编程》,ping也是普通用户执行,我的道理跟它一样啊?麻烦再补充一下.
回复

使用道具 举报

发表于 2004-3-17 23:40:43 | 显示全部楼层
对不起,可能误会你的意思了吧,我是指一些只能由管理员执行的程序。

你的:我本意是要以普通用户,执行超级用户才能执行的程序.
我不太清楚你是什么意思(我理解能力差--中国式教育摧残的结果)即使普通程序中也会有系统调用进入特权级的例程,不知和你说的情况是否有点相近?
回复

使用道具 举报

发表于 2004-3-17 23:41:22 | 显示全部楼层
他是不是说set-uid???
回复

使用道具 举报

发表于 2004-3-18 11:57:53 | 显示全部楼层
哦。对不起,我也只是个菜叶(菜鸟都算不上)。

这就怪了?
用setuid(0)试试(我试了可以)。一样的?我想和编译过程有关系,不知是否执行程序时因getuid是一个函数调用,这样,它在用户态下得到比如500,那不成了setuid(500)?不过看许多知名的软件都是用setuid(getuid())包括ping,这就不懂了?
回复

使用道具 举报

发表于 2004-3-18 12:35:14 | 显示全部楼层
你用chown root my, chmod +s my为程序设置了设置用户ID,程序运行时的有效用户ID就会被设置成root,就可以直接执行那些特权代码了
在执行完了特权代码后,再用setuid恢复成普通权限
回复

使用道具 举报

发表于 2004-3-18 12:47:11 | 显示全部楼层
哦,我明白了,我把这个函数的作用想反了。谢谢!
回复

使用道具 举报

 楼主| 发表于 2004-3-19 14:40:18 | 显示全部楼层
哈,我的问题还没解决呢?
我写了一个原始socket,必须是root才能创建raw socket,因此我使用了setuid(getuid());使得编译完程序后,再chown root my, chmod +s my,我就可以以普通用户执行这个程序了.
我这么做是按照书上的通用做法呀,怎么行不通呢?可能我的理解有误,但做法没有错.
回复

使用道具 举报

发表于 2004-3-19 17:08:24 | 显示全部楼层
总结一下,以免后来者如我般出错。

执行程序时(就产生一个进程),这个进程的有效用户id往往是这个进程的真实用户id(有效用户组id也一样)。但假如设置了该程序的模式位st_mode的set-user-id位,则这个进程的有效用户id变成该程序的所有者,那么,如果这个程序的所有者本来是root,那不就有根权限了吗?

另:
1.有效用户并不是能做程序的真实用户所能做的一切,即假如这个程序的有效用户与真实用户不一样,两者所能做的事有一点差异(在某些情况下)。但假如这个有效用户是根用户,就没有限制。

2.可用chmod("foo",S_ISUID|....(别的选项)) 或 如楼主chmod u+s foo来设置set-usr-id位。

3.总结让普通用户执行要根限的步骤:
   a    这个程序的所有者要是root
   b.   设置set-usr-id位

4.用setuid(getuid())的效果(我就在此犯错)。
  假如你在普通用户下执行这一步,一定要放在要执行的特权指令之后,因为你这步操作把有效用户id设置成了普通用户id(getuid()),从而改变了本来的有效用户id是根的情况。其实这一步改变程序的权限,作用是限制用户以后误用根权限,如果你没这个担心,不要也可。

不知楼主的setuid 是否也放错了地方?
回复

使用道具 举报

 楼主| 发表于 2004-3-19 17:58:37 | 显示全部楼层
哈,先谢谢楼上,我还没看太懂.不过已经解决了.问题出在chown root my
chmod +s my 中的my应该给出文件路径---/home/myname/my---哎,国内的书,乱七八糟,一点也不严谨.不过新问题又来了.执行my看不到我的具体效果.请各位在自己的机子上测试一下,我是没法子了.
等下子传上来.[/code]
回复

使用道具 举报

 楼主| 发表于 2004-3-22 22:56:01 | 显示全部楼层
[code:1]#include<unistd.h>
#include<stdlib.h>
#include<netdb.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<errno.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#define __FAVOR_BSD
#include<netinet/tcp.h>
#include<netinet/ip.h>
#include<string.h>
#include<stdio.h>
#include<ctype.h>
unsigned short ip_cksum(unsigned short *pcheck,int len)
{
int nleft=len;
int sum=0;
unsigned short *p=pcheck;
unsigned short result=0;
while(nleft>1){
sum+=*p++;
nleft-=2;}
if(nleft==1){
*(unsigned char*)(&result)=*(unsigned char*)p;
sum+=result;}
sum=(sum>>16)+(sum&0xFFFF);
sum+=(sum>>16);
result=~sum;
return result;}
int main(int argc,char* argv[])
{
struct hostent *host;
int fd;
int foo=1;
int s;
char buffer[40];
struct ip *ip=(struct ip*)buffer;
struct tcphdr *tcp=(struct tcphdr*)(buffer+sizeof(struct ip));
struct sockaddr_in sin,din;
if((host=gethostbyname(argv[1]))==0){
perror("gethostbyname");
exit(0);}
seteuid(geteuid());
if((fd=socket(AF_INET,SOCK_RAW,IPPROTO_RAW))<0)
{perror("socket failed!");
exit(0);}
sin.sin_addr=*((struct in_addr*)host->h_addr);
sin.sin_port=htons(9999);
inet_aton(argv[2],&din.sin_addr);
if((s=setsockopt(fd,IPPROTO_IP,IP_HDRINCL,(void*)&foo,sizeof(int)))!=0){
perror("setsockopt failed!");
exit(0);}
bzero(buffer,40*sizeof(char));
ip->ip_v=4;
ip->ip_hl=sizeof(struct ip)/4;
ip->ip_tos=0;
ip->ip_off=0;
ip->ip_id=0;
ip->ip_ttl=50;
ip->ip_p=IPPROTO_TCP;
ip->ip_src=din.sin_addr;
ip->ip_dst=sin.sin_addr;
ip->ip_len=sizeof(struct ip)+sizeof(struct tcphdr);
ip->ip_sum=0;
tcp->th_sport=htons(9999);
tcp->th_dport=htons(9999);
tcp->th_seq=htonl(0x12345678);
tcp->th_flags=TH_SYN;
tcp->th_off=sizeof(struct tcphdr)/4;
tcp->th_win=htons(2048);
tcp->th_sum=0;
tcp->th_sum=ip_cksum((u_short*)tcp,sizeof(struct tcphdr));
ip->ip_sum=ip_cksum((u_short*)ip,sizeof(struct ip));
sendto(fd,buffer,(sizeof(struct ip)+sizeof(struct tcphdr)),0,(struct sockaddr*)&sin,sizeof(struct sockaddr_in));
close(fd);
return(0);}[/code:1]
编译后即可在root下运行,功能:发送一个syn到tcp 9999.我用server 监听于9999端口 ,并且select ,但没有检测到.请帮我测试一下,能否实现?或者有什么错误.
回复

使用道具 举报

 楼主| 发表于 2004-3-22 23:00:27 | 显示全部楼层
哦,忘记了./'filename' ip源地址 ip目的地址
回复

使用道具 举报

 楼主| 发表于 2004-3-22 23:03:27 | 显示全部楼层
sorry 更正./filename dip sip
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-8 19:29 , Processed in 0.073210 second(s), 15 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表