通过unix域套接字ipc机制进行对等凭证

时间:2014-12-06 09:22:57

标签: unix ipc

我正在编写一个代码,用于通过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;
}

1 个答案:

答案 0 :(得分:0)

有关概述,请参阅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)