summaryrefslogtreecommitdiffstats
path: root/contrib/check_logins.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/check_logins.c')
-rw-r--r--contrib/check_logins.c351
1 files changed, 351 insertions, 0 deletions
diff --git a/contrib/check_logins.c b/contrib/check_logins.c
new file mode 100644
index 0000000..fa3ed17
--- /dev/null
+++ b/contrib/check_logins.c
@@ -0,0 +1,351 @@
1/*=================================
2 * check_logins - Nagios plugin
3 * Copyright (C) 2003 Dag Robøle
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * Authors email: drobole@broadpark.no
20 */
21//=================================
22#include <sys/types.h>
23#include <signal.h>
24#include <errno.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <unistd.h>
28#include <string.h>
29
30#include "config.h"
31#include "common.h"
32#include "utils.h"
33#include "popen.h"
34//=================================
35#define REVISION "$Revision$"
36#define COPYRIGHT "2003"
37#define AUTHOR "Dag Robole"
38#define EMAIL "drobole@broadpark.no"
39#define SUMMARY "Check for multiple user logins"
40
41#define check(func, errmsg) { if((func) == -1) die(STATE_UNKNOWN, errmsg); }
42#define checkz(func, errmsg) { if(!(func)) die(STATE_UNKNOWN, errmsg); }
43//=================================
44typedef struct USERNODE_TYP {
45 char *name;
46 char *host;
47 struct USERNODE_TYP* next;
48} USERNODE;
49//=================================
50char *progname = NULL;
51USERNODE *userlist = NULL, *adminlist = NULL;
52int warning_limit = 0, critical_limit = 0;
53
54void print_usage();
55void print_help();
56void process_arguments(int argc, char* *argv);
57void parse_wholine(const char *line, char *name, char *host);
58void node_create(USERNODE* *node, const char *name, const char *host);
59void node_free(USERNODE* *node);
60USERNODE* list_insert_sort_uniq(USERNODE* *list, USERNODE* *node);
61void list_free(USERNODE* *list);
62void cleanup();
63//=================================
64int main(int argc, char* *argv)
65{
66 FILE *who;
67 USERNODE *newnode, *nptra, *nptrb;
68 char buffer[BUFSIZ], username[BUFSIZ], hostname[BUFSIZ], *cptra, *cptrb;
69 char max_login_name[BUFSIZ], currname[BUFSIZ];
70 int max_login_count = 0, counter = 0, skip;
71 void (*old_sig_alrm)();
72
73 progname = argv[0];
74 if(atexit(cleanup))
75 die(STATE_UNKNOWN, "atexit failed\n");
76
77 if((old_sig_alrm = signal((int)SIGALRM, timeout_alarm_handler)) == SIG_ERR)
78 die(STATE_UNKNOWN, "signal failed\n");
79 alarm(timeout_interval);
80
81 process_arguments(argc, argv);
82
83 checkz(who = spopen(PATH_TO_WHO), "spopen failed\n");
84
85 while(fgets(buffer, sizeof(buffer), who) != NULL) {
86 parse_wholine(buffer, username, hostname);
87 skip = 0;
88 nptra = adminlist;
89
90 while(nptra != NULL) {
91 if(!strcmp(nptra->name, username)) {
92 skip = 1;
93 break;
94 }
95 nptra = nptra->next;
96 }
97 if(!skip) {
98 node_create(&newnode, username, hostname);
99 if(!list_insert_sort_uniq(&userlist, &newnode))
100 node_free(&newnode);
101 }
102 }
103
104 check(spclose(who), "spclose failed\n");
105
106 if(userlist != NULL) {
107 nptra = userlist;
108 strcpy(currname, nptra->name);
109 strcpy(max_login_name, nptra->name);
110 max_login_count = 1;
111 while(nptra != NULL) {
112 if(!strcmp(currname, nptra->name))
113 ++counter;
114 else {
115 if(counter > max_login_count) {
116 max_login_count = counter;
117 strcpy(max_login_name, currname);
118 }
119 strcpy(currname, nptra->name);
120 counter = 1;
121 }
122 nptra = nptra->next;
123 }
124
125 if(counter > max_login_count) {
126 max_login_count = counter;
127 strcpy(max_login_name, currname);
128 }
129 }
130
131 if(signal((int)SIGALRM, old_sig_alrm) == SIG_ERR)
132 die(STATE_UNKNOWN, "signal failed\n");
133
134 if(max_login_count) {
135 if(critical_limit && max_login_count >= critical_limit) {
136 printf("CRITICAL - User %s has logged in from %d different hosts\n", max_login_name, max_login_count);
137 return STATE_CRITICAL;
138 }
139 else if(warning_limit && max_login_count >= warning_limit) {
140 printf("WARNING - User %s has logged in from %d different hosts\n", max_login_name, max_login_count);
141 return STATE_WARNING;
142 }
143 }
144
145 printf("OK - No users has exceeded the login limits\n");
146 return STATE_OK;
147}
148//=================================
149void print_usage()
150{
151 fprintf(stderr, "Usage: %s [ -hV ] [ -w limit ] [ -c limit ] [ -u username1, ... ,usernameN ]\n", progname);
152}
153//=================================
154void print_help()
155{
156 print_revision(progname, REVISION);
157 printf("Copyright (c) %s %s <%s>\n\n%s\n\n", COPYRIGHT, AUTHOR, EMAIL, SUMMARY);
158 print_usage();
159 printf("\nDescription:\n"
160 "\tThis plugin supports the w (warning) and c (critical) options indicating the upper limits\n"
161 "\tof logins allowed before a warning is given.\n"
162 "\tThe output from %s is the username and number of login sessions for the user\n"
163 "\twho has the most login sessions (from different hosts) running at a given point in time.\n"
164 "\tThe u (users) option takes a comma separated list of usernames that will be ignored\n"
165 "\twhile scannig users.\n"
166 "\nOptions:\n"
167 "\t-h | --help\n\t\tShow this help message and exit\n"
168 "\t-V | --version\n\t\tShow version description\n"
169 "\t-w | --warning=INTEGER\n\t\tSet warning limit for logins (minimum value is 2)\n"
170 "\t-c | --critical=INTEGER\n\t\tSet critical limit for logins (minimum value is 2)\n"
171 "\t-u | --users=STRING\n\t\tSet usernames to be ignored\n"
172 "\nExamples:\n\t%s -w 3 -c 5\n"
173 "\t%s -w 3 -c 5 -u root,guest,jcarmack\n\n", progname, progname, progname);
174}
175//=================================
176void process_arguments(int argc, char* *argv)
177{
178 USERNODE *newnode;
179 int optch;
180 char buffer[BUFSIZ], *cptra;
181 static struct option long_opts[] = {
182 {"help", no_argument, 0, 'h'},
183 {"version", no_argument, 0, 'V'},
184 {"warning", required_argument, 0, 'w'},
185 {"critical", required_argument, 0, 'c'},
186 {"users", required_argument, 0, 'u'},
187 {0, 0, 0, 0},
188 };
189
190 while((optch = getopt_long(argc, argv, "hVw:c:u:", long_opts, NULL)) != -1) {
191 switch(optch) {
192 case 'h':
193 print_help();
194 exit(STATE_OK);
195 break;
196 case 'V':
197 print_revision(progname, REVISION);
198 exit(STATE_OK);
199 break;
200 case 'w':
201 if(!is_numeric(optarg)) {
202 print_usage();
203 die(STATE_UNKNOWN, "invalid options\n");
204 }
205 warning_limit = atoi(optarg) > 2 ? atoi(optarg) : 2;
206 break;
207 case 'c':
208 if(!is_numeric(optarg)) {
209 print_usage();
210 die(STATE_UNKNOWN, "invalid options\n");
211 }
212 critical_limit = atoi(optarg) > 2 ? atoi(optarg) : 2;
213 break;
214 case 'u':
215 strcpy(buffer, optarg);
216 cptra = strtok(buffer, ",");
217 while(cptra != NULL) {
218 node_create(&newnode, cptra, "(adminhost)");
219 list_insert_sort_uniq(&adminlist, &newnode);
220 cptra = strtok(NULL, ",");
221 }
222 break;
223 default:
224 print_usage();
225 exit(STATE_UNKNOWN);
226 break;
227 }
228 }
229
230 if(argc > optind) {
231 print_usage();
232 die(STATE_UNKNOWN, "invalid options\n");
233 }
234
235 if(!warning_limit && !critical_limit) {
236 print_usage();
237 die(STATE_UNKNOWN, "you must provide a limit for this plugin\n");
238 }
239
240 if(critical_limit && warning_limit > critical_limit) {
241 print_usage();
242 die(STATE_UNKNOWN, "warning limit must be less or equal critical limit\n");
243 }
244}
245//=================================
246void parse_wholine(const char *line, char *name, char *host)
247{
248 char buffer[BUFSIZ], *cptra, *cptrb, *display;
249 strcpy(buffer, line);
250
251 cptra = buffer;
252 checkz(cptrb = (char*)strchr(buffer, ' '), "strchr failed\n");
253 strncpy(name, cptra, cptrb-cptra);
254 name[cptrb-cptra] = '\0';
255
256 if((cptra = strchr(buffer, '(')) != NULL) // hostname found in source arg...
257 {
258 if(cptra[1] == ':') // local host
259 strcpy(host, "(localhost)");
260 else // extern host
261 {
262 checkz(cptrb = strchr(cptra, ')'), "strchr failed\n");
263 cptrb++;
264 strncpy(host, cptra, cptrb-cptra);
265 host[cptrb-cptra] = '\0';
266 }
267 }
268 else // no hostname in source arg, look in line arg...
269 {
270 checkz(cptra = strtok(buffer, " \t\r\n"), "strtok failed\n");
271 checkz(cptra = strtok(NULL, " \t\r\n"), "strtok failed\n");
272 if(cptra[0] == ':') // local host
273 strcpy(host, "(localhost)");
274 else // extern host
275 sprintf(host, "(%s)", cptra);
276 }
277
278 if((cptra = strchr(host, ':')) != NULL) // remove display if any...
279 strcpy(cptra, ")");
280}
281//=================================
282void node_create(USERNODE* *node, const char *name, const char *host)
283{
284 checkz(*node = (USERNODE*)malloc(sizeof(USERNODE)), "malloc failed\n");
285 checkz((*node)->name = (char*)malloc(strlen(name)+1), "malloc failed\n");
286 checkz((*node)->host = (char*)malloc(strlen(host)+1), "malloc failed\n");
287 (*node)->next = NULL;
288 strcpy((*node)->name, name);
289 strcpy((*node)->host, host);
290}
291//=================================
292void node_free(USERNODE* *node)
293{
294 free((*node)->name);
295 free((*node)->host);
296 free(*node);
297 *node = NULL;
298}
299//=================================
300USERNODE* list_insert_sort_uniq(USERNODE* *list, USERNODE* *node)
301{
302 char n1[BUFSIZ], n2[BUFSIZ];
303 USERNODE *last_nptr = NULL, *nptr = *list;
304
305 if(*list == NULL)
306 return(*list = *node);
307 else {
308 sprintf(n1, "%s %s", (*node)->name, (*node)->host);
309 while(nptr != NULL) {
310 sprintf(n2, "%s %s", nptr->name, nptr->host);
311 if(!strcmp(n1, n2))
312 return NULL;
313 else if(strcmp(n1, n2) < 0) {
314 if(last_nptr) {
315 last_nptr->next = *node;
316 (*node)->next = nptr;
317 }
318 else {
319 (*node)->next = *list;
320 *list = *node;
321 }
322 break;
323 }
324 else {
325 last_nptr = nptr;
326 nptr = nptr->next;
327 }
328 }
329 if(nptr == NULL)
330 last_nptr->next = *node;
331 }
332 return *node;
333}
334//=================================
335void list_free(USERNODE* *list)
336{
337 USERNODE *doe, *nptr = *list;
338 while(nptr != NULL) {
339 doe = nptr;
340 nptr = nptr->next;
341 node_free(&doe);
342 }
343 *list = NULL;
344}
345//=================================
346void cleanup()
347{
348 list_free(&userlist);
349 list_free(&adminlist);
350}
351//=================================