1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdbool.h>
4 #include <unistd.h>
5 #include <netdb.h>
6 #include <netinet/in.h>
7 #include <arpa/inet.h>
8 #include <memory.h>
9 #include <time.h>
10 #include <sys/socket.h>
11 #include "json.h"
12 
13 /*
14  * hare.c (C)2018 by Jan-Piet Mens <jp@mens.de>
15  */
16 
17 #define PORTNO  "8035"
18 
19 #define env(K)	( getenv(K) ? getenv(K) : "<unknown>" )
20 
_value(char * pamkey)21 JsonNode *_value(char *pamkey)
22 {
23 	char *p;
24 
25 	if ((p = getenv(pamkey)) != NULL)
26 		return (json_mkstring(p));
27 	return (json_mknull());
28 }
29 
30 
send_it(bool verbose,char * hostname,char * buf)31 int send_it(bool verbose, char *hostname, char *buf)
32 {
33 	struct addrinfo hints, *infoptr, *p;
34 	char host[256];
35 	int rc, sockfd;
36 
37 	memset(&hints, 0, sizeof hints);
38 	hints.ai_family = AF_INET;
39 	hints.ai_socktype = SOCK_DGRAM;
40 
41 	if ((rc = getaddrinfo(hostname, PORTNO, &hints, &infoptr)) != 0) {
42 		fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rc));
43 		return (1);
44 	}
45 
46 	for (p = infoptr; p != NULL; p = p->ai_next) {
47 		getnameinfo(p->ai_addr, p->ai_addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST);
48 		if (verbose) fprintf(stderr, "-> %s\n", host);
49 
50 		sockfd = socket(AF_INET, SOCK_DGRAM, 0);
51 
52 		if (sendto(sockfd, (void *)buf, strlen(buf), 0, p->ai_addr, p->ai_addrlen) < 0) {
53 			perror("sendto");
54 		}
55 		return (0);
56 	}
57 
58 	freeaddrinfo(infoptr);
59 
60 	return 0;
61 }
62 
63 
main(int argc,char ** argv)64 int main(int argc, char **argv)
65 {
66 	char *host = argv[1], myhostname[BUFSIZ];
67 	char *pamtype = env("PAM_TYPE");	/* Linux */
68 	char *pamsm = env("PAM_SM_FUNC");	/* FreeBSD */
69 	bool verbose = false;
70 	JsonNode *json;
71 	char *js;
72 
73 	if (strcmp(pamtype, "open_session") != 0 && strcmp(pamsm, "pam_sm_open_session") != 0) {
74 		fprintf(stderr, "Neither PAM open_session nor pam_sm_open_session detected\n");
75 		return 0;
76 	}
77 
78 	if (argc != 2) {
79 		fprintf(stderr, "Usage: %s address\n", *argv);
80 		exit(2);
81 	}
82 
83 	if (gethostname(myhostname, sizeof(myhostname)) != 0)
84 		strcpy(myhostname, "?");
85 
86 	json = json_mkobject();
87 	json_append_member(json, "tst", json_mknumber(time(0)));
88 	json_append_member(json, "hostname", json_mkstring(myhostname));
89 
90 	json_append_member(json, "user",    _value("PAM_USER"));
91 	json_append_member(json, "service", _value("PAM_SERVICE"));
92 	json_append_member(json, "rhost",   _value("PAM_RHOST"));
93 	json_append_member(json, "tty",	    _value("PAM_TTY"));
94 
95 	if ((js = json_stringify(json, NULL)) != NULL) {
96 		send_it(verbose, host, js);
97 		free(js);
98 	}
99 
100 	return (0);
101 }
102