【问题标题】:Peer credentials through unix domain socket ipc mechanism通过 unix 域套接字 IPC 机制的对等凭据
【发布时间】:2015-12-19 18:06:06
【问题描述】:

我正在编写一个代码,用于通过使用域套接字通过 ipc 连接到客户端进程的服务器进程来提取对等凭据。代码没有错误,但是运行时我没有得到对等进程的euid和gid。

服务器进程的代码是:

#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
//#include<ucred.h>
#define SCM_CREDENTIALS
# define UNIX_PATH_MAX 100

int getpeereid(int connection_fd,uid_t euid,gid_t gid)
{
struct ucred cred;
socklen_t len = sizeof(cred);

if (getsockopt(connection_fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) < 0)
        return (-1);
    euid =cred.uid;
    gid = cred.gid;
//int passcred=1;
//setsockopt(connection_fd,SOL_SOCKET,SO_PASSCRED,(void *)&passcred,sizeof(passcred));

printf("effective user id", euid);
printf("effective group id",gid);
return 0;
}

int connection_handler(int connection_fd)
{
 int nbytes;
 char buffer[1024];
 char msg[256];
//while(cont=recv(connection_fd,buffer,sizeof(buffer),0)>0)
//{ 
//write(1,buffer,cont)

nbytes = read(connection_fd, buffer, 256);
buffer[nbytes] = 0;

printf("MESSAGE FROM CLIENT: %s\n", buffer);
printf("enter the message");
scanf("%s",msg);
nbytes = snprintf(buffer, 256,msg);
write(connection_fd, buffer, nbytes);
//} 
 close(connection_fd);
 return 0;

}

int main(void)
{
 struct sockaddr_un address;
 int socket_fd, connection_fd,res;
 socklen_t address_length;
pid_t child;
uid_t eid;
gid_t gid;

 socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
 if(socket_fd < 0)
 {
  printf("socket() failed\n");
  return 1;
 }
printf("socket created\n");
 unlink("./demo_socket");

 /* start with a clean address structure */

memset(&address, 0, sizeof(struct sockaddr_un));

 address.sun_family = AF_UNIX;
 snprintf(address.sun_path, UNIX_PATH_MAX, "./demo_socket");

 if(bind(socket_fd,
         (struct sockaddr *) &address,
         sizeof(struct sockaddr_un)) != 0)
 {
  printf("bind() failed\n");
  return 1;
 }

 if(listen(socket_fd, 5) != 0)
 {
  printf("listen() failed\n");
  return 1;
 }

 while((connection_fd = accept(socket_fd,
                               (struct sockaddr *) &address,
                               &address_length)) > -1)
 {

// get the credentials
res=getpeereid(connection_fd,geteuid(),getgid());
if (res==0)
{
//if(res==0)
//{


child = fork();
  if(child == 0)
  {

   /* now inside newly created connection handling process */
   return connection_handler(connection_fd);
  }
}
  /* still inside server process */
  close(connection_fd);
//} 
}

 close(socket_fd);
 unlink("./demo_socket");
 return 0;
}

客户端代码

#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <string.h>
#define UNIX_PATH_MAX 100

int connection_handler(int socket_fd)
{
int nbytes;
char buffer[1024];
char mesg[256];
printf("enter the message");
scanf("%s",mesg);
//printf("message is %s",mesg);
nbytes = snprintf(buffer, 256,mesg);
//fgets(buffer,256,mesg);
//i=atoi(mesg);
write(socket_fd,buffer,nbytes);
//send(socket_fd,mesg,sizeof(mesg),0);
}
//nbytes = read(socket_fd, buffer, 256);
//buffer[nbytes] = 0;

//printf("MESSAGE FROM SERVER: %s\n", buffer);
//}

int main(void)
{
 struct sockaddr_un address;
 int  socket_fd, nbytes,i;
 pid_t child; 
 char buffer[256];
 //char mesg[100];
 socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
 if(socket_fd < 0)
 {
  printf("socket() failed\n");
  return 1;
 }
printf("socket created\n");
 /* start with a clean address structure */
 memset(&address, 0, sizeof(struct sockaddr_un));

 address.sun_family = AF_UNIX;
 snprintf(address.sun_path, UNIX_PATH_MAX, "./demo_socket");

 if(connect(socket_fd, 
            (struct sockaddr *) &address, 
            sizeof(struct sockaddr_un)) != 0)
 {
  printf("connect() failed\n");

 return 1;
}


child=fork();
while(child==0)
{
return connection_handler(socket_fd);
//printf("connection established\n");
//printf("enter the message");
//scanf("%s",mesg);
//printf("message is %s",mesg);
//bytes = snprintf(buffer, 256,mesg);
//fgets(buffer,256,mesg);
//i=atoi(mesg);
//write(socket_fd,buffer,nbytes);
//send(socket_fd,mesg,sizeof(mesg),0);
}

nbytes = read(socket_fd, buffer, 256);
buffer[nbytes] = 0;

printf("MESSAGE FROM SERVER: %s\n", buffer);

 close(socket_fd);
 return 0;
}

【问题讨论】:

    标签: unix ipc


    【解决方案1】:

    请参阅http://www.thomasstover.com/uds.html 以获得良好的概述。

    如果服务器是Linux,主要问题是缺少_GNU_SOURCE。下面的完整补丁,它有一些小的变化只是为了摆脱gcc -Wall -Werror -pedantic -std=c99 错误和警告。

    --- server.c.orig   2014-12-06 13:23:09.138472871 +0200
    +++ server.c    2014-12-06 13:21:31.962475754 +0200
    @@ -1,3 +1,4 @@
    +#define _GNU_SOURCE
     #include <stdio.h>
     #include <sys/socket.h>
     #include <sys/un.h>
    @@ -5,7 +6,6 @@
     #include <unistd.h>
     #include <string.h>
     //#include<ucred.h>
    -#define SCM_CREDENTIALS
     # define UNIX_PATH_MAX 100
    
     int getpeereid(int connection_fd,uid_t euid,gid_t gid)
    @@ -20,8 +20,8 @@
     //int passcred=1;
     //setsockopt(connection_fd,SOL_SOCKET,SO_PASSCRED,(void *)&passcred,sizeof(passcred));
    
    -printf("effective user id", euid);
    -printf("effective group id",gid);
    +printf("effective user id %d", euid);
    +printf("effective group id %d",gid);
     return 0;
     }
    
    @@ -40,7 +40,7 @@
     printf("MESSAGE FROM CLIENT: %s\n", buffer);
     printf("enter the message");
     scanf("%s",msg);
    -nbytes = snprintf(buffer, 256,msg);
    +nbytes = snprintf(buffer, 256, "%s", msg);
     write(connection_fd, buffer, nbytes);
     //} 
      close(connection_fd);
    @@ -54,8 +54,6 @@
      int socket_fd, connection_fd,res;
      socklen_t address_length;
     pid_t child;
    -uid_t eid;
    -gid_t gid;
    
      socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
      if(socket_fd < 0)
    

    【讨论】:

    • 您本可以告诉他他缺少printf 的格式选项,这就是为什么他没有看到任何euid 或gid 而不是这堵差异墙。跨度>
    • 我进行了更改并执行了。我的错误错过了格式选项!但执行后我得到相同的euid和gid,即euid = 1000和gid = 1000。这可能是什么原因?
    • @Neha 不是用户的 1000 UID 和 GID,谁在运行客户端?我尝试从 2 个不同的用户运行客户端(必须更改 ./demo.socket 的权限才能连接)并且我得到了正确的结果。
    • @Petesh 问题不仅仅是格式化:没有_GNU_SOURCE_ cred 未定义。
    • 好的!知道了。感谢您的帮助。赞赏
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多