1 /* cvm/cvm-pwfile.c - Alternate passwd file CVM module
2  * Copyright (C) 2010  Bruce Guenter <bruce@untroubled.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18 #include <bglibs/sysdeps.h>
19 #include <errno.h>
20 #include <pwd.h>
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include <bglibs/ibuf.h>
25 #include <bglibs/msg.h>
26 #include <pwcmp/client.h>
27 
28 #include "module.h"
29 
30 const char program[] = "cvm-pwfile";
31 
32 static const char* pwfilename;
33 
cvm_module_init(void)34 int cvm_module_init(void)
35 {
36   if ((pwfilename = getenv("CVM_PWFILE_PATH")) == 0) return CVME_CONFIG;
37   if (!pwcmp_start(getenv("CVM_PWFILE_PWCMP"))) return CVME_GENERAL;
38   return 0;
39 }
40 
parse_rest(char * rest)41 static int parse_rest(char* rest)
42 {
43   /* Format: "UID:GID:NAME,other:DIR:SHELL" */
44   char* tmp;
45   cvm_fact_userid = strtoul(rest, &tmp, 10);
46   if (*tmp != ':') return 0;
47   rest = tmp + 1;
48 
49   cvm_fact_groupid = strtoul(rest, &tmp, 10);
50   if (*tmp != ':') return 0;
51   rest = tmp + 1;
52 
53   cvm_fact_realname = rest;
54   if ((tmp = strchr(rest, ',')) != 0) {
55     *tmp++ = 0;
56     rest = tmp;
57   }
58 
59   if ((tmp = strchr(rest, ':')) == 0) return 0;
60   *tmp++ = 0;
61   cvm_fact_directory = rest = tmp;
62 
63   if ((tmp = strchr(rest, ':')) == 0) return 0;
64   *tmp++ = 0;
65   cvm_fact_shell = rest = tmp;
66 
67   cvm_fact_groupname = 0;
68   return 1;
69 }
70 
71 static char* passwd;
72 static char* rest;
73 static str line;
74 
cvm_module_lookup(void)75 int cvm_module_lookup(void)
76 {
77   ibuf pwfile;
78   long namelen;
79 
80   if (cvm_module_credentials[CVM_CRED_ACCOUNT].s == 0)
81     return CVME_NOCRED;
82   passwd = 0;
83   namelen = cvm_module_credentials[CVM_CRED_ACCOUNT].len;
84 
85   if (!ibuf_open(&pwfile, pwfilename, 0)) return CVME_IO;
86   while (ibuf_getstr(&pwfile, &line, LF)) {
87     line.s[--line.len] = 0;
88     if (strncasecmp(cvm_module_credentials[CVM_CRED_ACCOUNT].s, line.s, namelen) == 0
89 	&& line.s[namelen] == ':') {
90       passwd = line.s + namelen;
91       *passwd++ = 0;
92       break;
93     }
94   }
95   ibuf_close(&pwfile);
96   if (passwd == 0) return CVME_PERMFAIL;
97 
98   if ((rest = strchr(passwd, ':')) == 0 || rest == passwd)
99     return CVME_PERMFAIL;
100   *rest++ = 0;
101   return 0;
102 }
103 
cvm_module_authenticate(void)104 int cvm_module_authenticate(void)
105 {
106   CVM_CRED_REQUIRED(PASSWORD);
107   switch (pwcmp_check(cvm_module_credentials[CVM_CRED_PASSWORD].s, passwd)) {
108   case 0: return 0;
109   case -1: return CVME_IO | CVME_FATAL;
110   default: return CVME_PERMFAIL;
111   }
112 }
113 
cvm_module_results(void)114 int cvm_module_results(void)
115 {
116   cvm_fact_username = line.s;
117   if (!parse_rest(rest)) return CVME_CONFIG;
118   return 0;
119 }
120 
cvm_module_stop(void)121 void cvm_module_stop(void)
122 {
123   pwcmp_stop();
124 }
125