Solaris 11.3 ucred_getprojid incorrect behavior? - solaris

I've written a pair of TCP client/server which each call getpeerucred on the other and then call ucred_getprojid print out the project id their respective peer. I see the following results:
Within within any distinct zone (global or zlogin to any single zone) the client/server pair both report proper project id from their peer.
# /usr/bin/id -p
uid=0(root) gid=0(root) projid=1(user.root)
# ./bind 5000
Binding to port: 5000
project id: 10
---------------
$ /usr/bin/id -p
uid=100(rpaisley) gid=10(staff) projid=10(group.staff)
$ ./connect 127.0.0.1 5000
project id: 1
With Trusted Extensions enabled using two differently labeled zones (it doesn't seem to matter if there's any dominance relationship, the same behavior applies) across a Multi-Level port both report 0 which is neither correct, nor the -1 claimed from the ucred_getprojid manual page for when the project ID is not available.
# /usr/bin/id -p
uid=0(root) gid=0(root) projid=1(user.root)
# ./bin/bind 2000
Binding to port: 2000
project id: 0
---------------
$ /usr/bin/id -p
uid=100(rpaisley) gid=10(staff) projid=10(group.staff)
$ ./bin/connect 10.10.10.1 2000
project id: 0
Source code for server (named bind) is below. Program requires -ltsol -lsocket -lnsl
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <ucred.h>
#include <unistd.h>
int
main(int argc, char **argv)
{
if(2 != argc) {
fprintf(stderr, "Usage: %s <port>\n", *argv);
return EXIT_FAILURE;
}
int port;
char unused;
if(1 != sscanf(argv[1], "%d%c", &port, &unused)) {
fprintf(stderr, "Failed to parse port: %s\n", argv[1]);
return EXIT_FAILURE;
}
int s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(-1 == s) {
perror("socket");
return EXIT_FAILURE;
}
struct sockaddr_in local;
memset(&local, 0, sizeof(local));
local.sin_family = AF_INET;
local.sin_addr.s_addr = htonl(INADDR_ANY);
local.sin_port = htons(port);
printf("Binding to port: %d\n", port);
if(-1 == bind(s, (struct sockaddr *)&local, sizeof(local))) {
perror("bind");
close(s);
return EXIT_FAILURE;
}
if(-1 == listen(s, 1)) {
perror("listen");
close(s);
return EXIT_FAILURE;
}
int c;
struct sockaddr_in client;
unsigned int clientlen = sizeof(client);
c = accept(s, (struct sockaddr *)&client, &clientlen);
if(-1 == c) {
perror("accept");
close(s);
return EXIT_FAILURE;
}
close(s);
ucred_t *cred = NULL;
if(-1 == getpeerucred(c, &cred)) {
perror("getpeerucred");
close(c);
return EXIT_FAILURE;
}
printf("project id: %d\n", ucred_getprojid(cred));
ucred_free(cred);
close(c);
return EXIT_SUCCESS;
}
Source code for client (named connect) Program requires -ltsol -lsocket -lnsl
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <ucred.h>
#include <unistd.h>
int
main(int argc, char **argv)
{
if(3 != argc) {
fprintf(stderr, "Usage: %s <ip addr> <port>\n", *argv);
return EXIT_FAILURE;
}
int port;
char unused;
if(1 != sscanf(argv[2], "%d%c", &port, &unused)) {
fprintf(stderr, "Failed to parse port: %s\n", argv[2]);
return EXIT_FAILURE;
}
struct sockaddr_in srvaddr;
memset(&srvaddr, 0, sizeof(srvaddr));
srvaddr.sin_family = AF_INET;
srvaddr.sin_port = htons(port);
if(0 == inet_aton(argv[1], &srvaddr.sin_addr)) {
fprintf(stderr, "Address invalid: %s\n", argv[1]);
return EXIT_FAILURE;
}
int s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(-1 == s) {
perror("socket");
return EXIT_FAILURE;
}
if(-1 == connect(s, (struct sockaddr *)&srvaddr, sizeof(srvaddr))) {
perror("connect");
close(s);
return EXIT_FAILURE;
}
ucred_t *cred = NULL;
if(-1 == getpeerucred(s, &cred)) {
perror("getpeerucred");
close(s);
return EXIT_FAILURE;
}
printf("project id: %d\n", ucred_getprojid(cred));
ucred_free(cred);
close(s);
return EXIT_SUCCESS;
}

Related

Tcp socket using C (server)

I coded a program in C of a tcp socket but once executed, the server returns an error from the accept function but i can't find out why..
If you guys can help me, that would be appreciated. Also, if you have any advice on the way i programmed this, please feel free to tell me.
Here is my code :
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main(int argc, char *argv[])
{
int listenSocket, status, socketClient;
unsigned short int msgLength;
struct addrinfo hints, *servinfo;
struct sockaddr_in clientAddress;
socklen_t clientAddressLength = sizeof clientAddress;
char msg[101];
//Test port number
if (argc != 2) {
fprintf(stderr,"Usage : %s [NUMERO_PORT]\n",argv[0]);
return 2;
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET; // IPv4
hints.ai_socktype = SOCK_DGRAM; // UDP
hints.ai_flags = 0; //Car on fait le test sur la meme machine
if ((status = getaddrinfo(NULL, argv[1], &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
return 3;
}
if ((listenSocket = socket(servinfo->ai_family, servinfo-
>ai_socktype, servinfo->ai_protocol)) == -1) {
perror("socket:");
return 4;
}
if (bind(listenSocket, servinfo->ai_addr, servinfo->ai_addrlen) ==
-1) {
close(listenSocket);
perror("bind:");
return 5;
}
listen(listenSocket,5);
int sizeOfSockAddr = sizeof(clientAddress);
socketClient= accept(listenSocket, NULL, NULL);
if (socketClient < 0) {
fprintf(stderr,"Erreur accept\n");
return 6;
}
freeaddrinfo(servinfo);
printf("Waiting for a client's request %s\n", argv[1]);
while (1) {
//some things
}
}`

The client sents message to the server and shows error couldn't sent, whats the problem in the program

The client program:
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define LEN 256
int main(int argc, char *argv[]) {
struct addrinfo hints;
struct addrinfo *result, *rp;
int sock, s, n, r;
char message[256] , receive[1024];
int msglen, recvlen;
if (argc < 3)
{
fprintf(stderr, "Usage: %s host port msg...\n", argv[0]);
exit(EXIT_FAILURE);
}
/* Obtain address(es) matching host/port */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM; /* streaming socket */
hints.ai_flags = 0;
hints.ai_protocol = 0; /* Any protocol */
s = getaddrinfo(argv[1], argv[2], &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
/* getaddrinfo() returns a list of address structures.
Try each address until we successfully connect(2).
If socket(2) (or connect(2)) fails, we (close the socket
and) try the next address. */
for (rp = result; rp != NULL; rp = rp->ai_next) {
sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sock == -1)
continue;
if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1)
break; /* Success */
close(sock);
}
if (rp == NULL) { /* No address succeeded */
fprintf(stderr, "Could not connect\n");
exit(EXIT_FAILURE);
}
/* Send remaining command-line arguments as separate
datagrams, and read responses from server */
while(1)
{
bzero(message, LEN );
fgets(message, LEN, stdin);
printf("The server sent: %s\n",message);
n = send(sock, message, strlen(message), 0);
{
fprintf(stderr, "Could not send\n");
exit(EXIT_FAILURE);
}
bzero(message, 255);
n = recv(sock, message, LEN, 0);
if (n < 0)
{
fprintf(stderr, "Could not receive\n");
exit(EXIT_FAILURE);
}
printf("The client received: %s\n", message);
int i = strncmp("Exit", receive, 4);
if(i == 0)
break;
}
return 0;
}
The server program:
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#define LEN 256
int main(int argc, char *argv[]) {
struct addrinfo hints;
struct addrinfo *result, *rp;
struct sockaddr_in storage;
int sock, s,l,a,n;
char receive[LEN], response[1024];
int recvlen = strlen(receive);
pid_t childpid;
if (argc != 2)
{
fprintf(stderr, "Usage: %s port\n", argv[0]);
exit(EXIT_FAILURE);
}
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM; /* Datagram socket */
hints.ai_flags = 0; /* For wildcard IP address */
hints.ai_protocol = 0; /* Any protocol */
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
s = getaddrinfo(NULL, argv[1], &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
/* getaddrinfo() returns a list of address structures.
Try each address until we successfully bind(2).
If socket(2) (or bind(2)) fails, we (close the socket
and) try the next address. */
for (rp = result; rp != NULL; rp = rp->ai_next) {
sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sock == -1)
continue;
if (bind(sock, rp->ai_addr, rp->ai_addrlen) == 0)
break; /* Success */
close(sock);
}
if (rp == NULL) { /* No address succeeded */
fprintf(stderr, "Could not bind\n");
exit(EXIT_FAILURE);
}
l = listen(sock, 5);
if(l != 0)
{
fprintf(stderr, "error in listening\n");
exit(EXIT_FAILURE);
}
socklen_t str_storage = sizeof(storage);
a = accept(sock, (struct sockaddr*)&storage, &str_storage);
if(a < 0)
{
fprintf(stderr, "the acceptance is not done\n");
exit(EXIT_FAILURE);
}
while(1)
{
bzero(receive, LEN);
n = recv(a, receive, LEN , 0);
if(n < 0)
{
fprintf(stderr, "error in reading\n");
exit(EXIT_FAILURE);
}
printf("The client message: %s\n ", receive);
bzero(receive, LEN);
fgets(receive, LEN, stdin);
n = send(a, receive, recvlen, 0);
if(n < 0)
{
fprintf(stderr, "error in replying\n");
exit(EXIT_FAILURE);
}
int i = strncmp("Exit", receive, 4);
if(i == 0)
break;
printf("The server message: %s\n", receive);
}
close(a);
return 0;
}
linux output both sides:
$ ./client localhost 5690
deeeksha hey
The server sent: deeeksha hey
Could not send
server output:
$ ./server 5690
The client message: deeeksha hey
n = send(sock, message, strlen(message), 0);
{
fprintf(stderr, "Could not send\n");
exit(EXIT_FAILURE);
}
Your client is executing this block no matter if the send was successful or not. It looks like you've forgot to check for if (n<0) but instead just had a block without any condition. Likely a case of copy & paste from somewhere else in your code by forgetting to copy the first line.

Only the first message is reaching from client to server in socket programming but the further messages sent from client are not reaching the server

I have put a while loop in both client and server to send and recieve messages but only first message is reaching the server. There after the messages sent from client are not reaching the server.
server side:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <netdb.h>
int main(int argc, char *argv[])
{
int socks,portno;
struct sockaddr_in server,client;
int newsock,n;
char buffer[5000];
int cli_len;
if(argc < 2)
{
perror("\ninsufficient inputs");
exit(1);
}
if((socks = socket(AF_INET,SOCK_STREAM,0)) < 0)
{
perror("\nsocket creation error");
exit(1);
}
printf("\nsocket successfully created");
bzero((char *) &server, sizeof(server));
server.sin_family = AF_INET;
portno = atoi(argv[1]);
server.sin_port = htons(portno);
server.sin_addr.s_addr = INADDR_ANY;
if((bind(socks,(struct sockaddr *) &server,sizeof(server))) > 0)
{ //socket binding
perror("\nsocket binding failed");
exit(1);
}
printf("\nsocket binding successfull");
if(listen(socks,5) < 0)
{
perror("\nerror in listening");
exit(1);
}
printf("\nlisten succesfull");
while(1)
{
cli_len = sizeof client;
newsock = accept(socks, (struct sockaddr *) &client,&cli_len);
bzero(buffer,5000);
if( (n = recv(newsock,buffer,5000,0)) < 0) //recieving the message
{
perror("\nreading from socket failed");
exit(1);
}
printf("read message:%s",buffer);
//bzero(buffer,5000);
//buffer[5000] = "got ur message";
if(( n = write(newsock,"got ur message",14)) < 0)
{
perror("\nwrite failed");
exit(1);
}
}
return 0;
}
Client:
on the client side it's asking the next message to be sent but all the messages after first message are not reaching the server.
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
int main(int argc, char *argv[])
{
struct sockaddr_in server;
struct hostent *host;
char buffer[5000];
int portno,socky,n;
if(argc < 3)
{
perror("insufficient inputs"); //checking the inputs
exit(1);
}
if((socky = socket(AF_INET,SOCK_STREAM,0)) < 0)
{
perror("\nerror in socket creation"); //socket creation
exit(1);
}
printf("\nsocket successfully created");
server.sin_family = AF_INET;
portno = atoi(argv[2]);
server.sin_port = htons(portno);
host = gethostbyname(argv[1]);
if(host == NULL)
{
perror("\nerror in getting host address");
exit(1);
}
memcpy (&server.sin_addr.s_addr, host->h_addr,host->h_length);
if((connect(socky,&server,sizeof(server)))<0) //connecting to server
{
perror("\nerror in connection");
exit(1);
}
while(1)
{
bzero(buffer,5000);
printf("\nenter the message");
fgets(buffer,5000,stdin);
printf("u have entered the messge:%s",buffer);
if((n = write(socky,buffer,strlen(buffer))) < 0) //writing to socket
{
perror("\nerror in writing the message");
exit(1);
}
bzero(buffer,1000);
if (n = (read(socky,buffer,1000)) < 0) //reading from socket
{
perror("\nerror in reading from socket");
exit(1);
}
printf("\nmessage recieved:%s",buffer);
}
return 0;
}

UDP socket not responding

I'm writing a sample of c udp socket.
This is the client
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <arpa/inet.h>
int
main(int argc, char *argv[]) {
if (argc < 3) {
fprintf(stderr, "Usage: %s ip port\n", argv[0]);
exit(1);
}
int sock;
char *server_ip;
unsigned short server_port;
struct sockaddr_in cliAddr, serAddr;
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
fprintf(stderr, "socket failed\n");
exit(1);
}
server_ip = argv[1];
server_port = atoi(argv[2]);
memset(&cliAddr, 0, sizeof(cliAddr));
cliAddr.sin_family = AF_INET;
cliAddr.sin_addr.s_addr = htonl(INADDR_ANY);
cliAddr.sin_port = htons(21152);
if (bind(sock, (struct sockaddr *) &cliAddr, sizeof(struct sockaddr)) < 0) {
fprintf(stderr, "bind failed\n");
exit(1);
}
memset(&serAddr, 0, sizeof(serAddr));
serAddr.sin_family = AF_INET;
serAddr.sin_addr.s_addr = inet_addr(server_ip);
serAddr.sin_port = htons(server_port);
if (sendto(sock, "hello", 5, 0, (struct sockaddr *) (&serAddr), sizeof(serAddr)) == -1) {
fprintf(stderr, "sendto failed\n");
exit(1);
}
printf("send success\n");
int n;
char recvstr[50];
if ((n = recvfrom(sock, &recvstr, 50, 0, NULL, NULL)) < 0) {
fprintf(stderr, "recvfrom failed\n");
exit(1);
}
printf("receive success: %s\n", recvstr);
printf("from %s:%d\n", inet_ntoa(serAddr.sin_addr), ntohs(serAddr.sin_port));
exit(0);
}
And this is the server
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
int
main(int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "Usage: %s port\n", argv[0]);
exit(1);
}
int sock, n;
struct sockaddr_in servaddr, cliaddr;
char recvstr[50];
socklen_t cliaddrlen;
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
fprintf(stderr, "socket failed\n");
exit(1);
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(atoi(argv[1]));
if (bind(sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
fprintf(stderr, "bind failed\n");
exit(1);
}
cliaddrlen = sizeof(cliaddr);
if ((n = recvfrom(sock, recvstr, 50, 0, (struct sockaddr *) &cliaddr, &cliaddrlen)) < 0) {
fprintf(stderr, "recvfrom failed\n");
exit(1);
}
printf("client ip: %s, client port: %d\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
if (sendto(sock, "hello from server", 17, 0, (struct sockaddr *) &cliaddr, cliaddrlen) == -1) {
fprintf(stderr, "sendto failed\n");
exit(1);
}
printf("send success\n");
exit(0);
}
It works fine when client and server are in the local.
Such as "./server 21151" and "./client 127.0.0.1 21151".
The server will get:
client ip: 127.0.0.1, client port: 21152
send success
And the client will get:
send success
receive success: hello from serverB
from 127.0.0.1:21151
But when i change the ip to public ip.The client cannot get the response
from server.
The client will stop at the function recvfrom.
Any ideas?
Let me guess - you are running this on a Mac and the firewall is on? The default filtering rules will allow sending UDP out and receiving a response (the client), but will not allow to receive unsolicited datagrams on an open socket (the server).
Your code is fine otherwise, though you don't necessarily need to bind(2) the client side of the socket. The kernel will assign next available high-numbered port for the source. You might instead consider using connect(2) on the client if you plan on any extended conversation between given client and server.
You also always want to explicitly zero-terminate strings received from the network. Not doing this has been the source of endless remote exploits.

Fail to connect two sockets which are bound with two public IP address in a server

I tried to setup a XSTUNT server on Linux(http://www.cis.nctu.edu.tw/~gis87577/xDreaming/XSTUNT/index.html) to do p2p traversal, but failed. I read the source code of it. I found the application creates two TCP sockets and then bind them to the two public IP addresses respectively. The remote client is able to connect only one of the public IP address.
So I wrote a simple server application to test this environment.
On the remote client, I use this two commands
"nc [public IP_A] [PORT]" and
"nc [public IP_B] [PORT]"
to try to connect to the server. Only one is successful, while the other fail. I have sniffer the traffic on the client, the nc which is failed can not get "SYN-ACK" package from the server. Is it the route problem? My two public interfaces do NOT have special gateway. Because I use PPPoE to connect to the Internet. So I just get ppp0 and ppp1. I don't know how to change the route table if the route table cause this problem.
However, If I do these two command on the server which is running my sever application, both commands are successful. Who can tell me why?
NOTE: I compiled this server application on Windows with cygwin. The result is the same.
Here is the code of my server application
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <unistd.h>
#define SERVPORT 3333 /* Listen Port */
#define BACKLOG 10
int main(int argc, char **argv)
{
int sockfd[2],client_fd;
struct sockaddr_in my_addr;
struct sockaddr_in remote_addr; /* client socket info */
int sin_size;
int maxfd;
fd_set rfds;
int i;
if(argc != 3)
{
printf("Usage: %s <IP_1> <IP_2>\n", argv[0]);
return 1;
}
for(i = 0; i < 2; i++)
{
if ((sockfd[i] = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket error!"); exit(1);
}
else
{
printf("Create sockfd[%d] = %d\n", i, sockfd[i]);
}
}
// set the first Socket
my_addr.sin_family=AF_INET;
my_addr.sin_port=htons(SERVPORT);
my_addr.sin_addr.s_addr = inet_addr(argv[1]);
bzero(&(my_addr.sin_zero),8);
if (bind(sockfd[0], (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
perror("bind error!");
exit(1);
}
// set the second Socket
my_addr.sin_family=AF_INET;
my_addr.sin_port=htons(SERVPORT);
my_addr.sin_addr.s_addr = inet_addr(argv[2]);
bzero(&(my_addr.sin_zero),8);
if (bind(sockfd[1], (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
perror("bind error!");
exit(1);
}
for(i = 0; i < 2; i++)
{
if (listen(sockfd[i], BACKLOG) == -1) {
perror("listen error!");
exit(1);
}
}
if(sockfd[0] > sockfd[1])
maxfd = sockfd[0];
else
maxfd = sockfd[1];
while(1) {
FD_ZERO(&rfds);
FD_SET(sockfd[0], &rfds);
FD_SET(sockfd[1], &rfds);
printf("waiting client\n");
select(maxfd + 1, &rfds, NULL, NULL, NULL);
sin_size = sizeof(struct sockaddr_in);
if(FD_ISSET(sockfd[0], &rfds))
{
printf("sockfd[0](%s) is readable\n", argv[1]);
if ((client_fd = accept(sockfd[0], (struct sockaddr *)&remote_addr, (socklen_t *)&sin_size)) == -1) {
perror("accept error");
continue;
}
}
else if(FD_ISSET(sockfd[1], &rfds))
{
printf("sockfd[1](%s) is readable\n", argv[2]);
if ((client_fd = accept(sockfd[1], (struct sockaddr *)&remote_addr, (socklen_t *)&sin_size)) == -1) {
perror("accept error");
continue;
}
}
else
{
printf("select error\n");
continue;
}
printf("received a connection from %s:%d\n\n", (char *)inet_ntoa(remote_addr.sin_addr), ntohs(remote_addr.sin_port));
if (!fork()) { /* child process */
if (send(client_fd, "Hello, you are connected!\n", 26, 0) == -1)
perror("send error!");
close(client_fd);
exit(0);
}
close(client_fd);
}
}