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