1 /* cvm/module_request.c - Request parsing code
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 <stdlib.h>
19 #include <string.h>
20 #include "module.h"
21 #include "protocol.h"
22 
23 const char* cvm_account_name;
24 const char* cvm_account_domain;
25 
26 unsigned char cvm_module_inbuffer[BUFSIZE+1];
27 unsigned cvm_module_inbuflen;
28 
29 const char* cvm_module_lookup_secret = 0;
30 
31 str cvm_module_credentials[CVM_CRED_MAX+1];
32 
cvm_module_init_request(void)33 void cvm_module_init_request(void)
34 {
35   /* Determine if the module is to operate in lookup mode, and if not
36      set the local credential values appropriately. */
37   cvm_module_lookup_secret = getenv("CVM_LOOKUP_SECRET");
38   memset(cvm_module_credentials, 0, sizeof cvm_module_credentials);
39 }
40 
v1copy_advance(const char ** ptr,char ** buf,unsigned * len)41 static int v1copy_advance(const char** ptr, char** buf, unsigned* len)
42 {
43   char* tmp;
44   if ((tmp = memchr(*buf, 0, *len)) == 0) return 0;
45   ++tmp;
46   if (*len < (unsigned)(tmp - *buf)) return 0;
47   *ptr = *buf;
48   *len -= tmp - *buf;
49   *buf = tmp;
50   return 1;
51 }
52 
parse_v1_input(void)53 static int parse_v1_input(void)
54 {
55   char* buf;
56   unsigned len;
57   const char* cred;
58 
59   /* Prevent buffer run-off by ensuring there is at least one NUL byte */
60   cvm_module_inbuffer[BUFSIZE] = 0;
61   buf = (char*)cvm_module_inbuffer + 1;
62   len = cvm_module_inbuflen - 1;
63 
64   /* Account name */
65   if (!v1copy_advance(&cred, &buf, &len)) return CVME_BAD_CLIDATA;
66   if (!str_copys(&cvm_module_credentials[CVM_CRED_ACCOUNT], cred))
67     return CVME_IO;
68 
69   /* Domain name */
70   if (!v1copy_advance(&cred, &buf, &len)) return CVME_BAD_CLIDATA;
71   if (*cred != 0
72       && !str_copys(&cvm_module_credentials[CVM_CRED_DOMAIN], cred))
73     return CVME_IO;
74 
75   if (len > 1) {
76     /* Allow for only a single credential if one is present.
77        No existing CVM1 module could handle more than one. */
78     if (!v1copy_advance(&cred, &buf, &len))
79       return CVME_BAD_CLIDATA;
80     if (!str_copys((cvm_module_lookup_secret != 0)
81 		   ? &cvm_module_credentials[CVM_CRED_SECRET]
82 		   : &cvm_module_credentials[CVM_CRED_PASSWORD], cred))
83       return CVME_IO;
84   }
85 
86   if (len != 1) return CVME_BAD_CLIDATA;
87   return 0;
88 }
89 
parse_v2_input(void)90 static int parse_v2_input(void)
91 {
92   unsigned i;
93   unsigned len;
94   unsigned type;
95   for (i = cvm_module_inbuffer[1] + 2;
96        i < cvm_module_inbuflen - 2;
97        i += len + 2) {
98     type = cvm_module_inbuffer[i];
99     len = cvm_module_inbuffer[i+1];
100     if (type <= CVM_CRED_MAX)
101       if (!str_copyb(&cvm_module_credentials[type],
102 		     (char*)cvm_module_inbuffer+i+2, len))
103 	return CVME_IO;
104   }
105   if (i >= cvm_module_inbuflen
106       || cvm_module_inbuffer[i] != 0)
107     return CVME_BAD_CLIDATA;
108   return 0;
109 }
110 
parse_input(void)111 static int parse_input(void)
112 {
113   if (cvm_module_inbuffer[0] == CVM2_PROTOCOL)
114     return parse_v2_input();
115   if (cvm_module_inbuffer[0] == CVM1_PROTOCOL)
116     return parse_v1_input();
117   return CVME_BAD_CLIDATA;
118 }
119 
cvm_module_handle_request(void)120 int cvm_module_handle_request(void)
121 {
122   int code;
123   unsigned i;
124   for (i = 0; i <= CVM_CRED_MAX; ++i)
125     cvm_module_credentials[i].len = 0;
126   cvm_module_fact_start();
127   if ((code = parse_input()) != 0) return code;
128   if (cvm_module_lookup_secret != 0 && *cvm_module_lookup_secret != 0) {
129     if (cvm_module_credentials[CVM_CRED_SECRET].len == 0
130 	|| str_diffs(&cvm_module_credentials[CVM_CRED_SECRET],
131 		     cvm_module_lookup_secret) != 0)
132       return CVME_NOCRED;
133   }
134   if ((code = cvm_module_lookup()) != 0) return code;
135   if (cvm_module_lookup_secret == 0)
136     if ((code = cvm_module_authenticate()) != 0) return code;
137   if ((code = cvm_module_results()) != 0) return code;
138   cvm_module_fact_str(CVM_FACT_USERNAME, cvm_fact_username);
139   cvm_module_fact_uint(CVM_FACT_USERID, cvm_fact_userid);
140   cvm_module_fact_uint(CVM_FACT_GROUPID, cvm_fact_groupid);
141   if (cvm_fact_realname)
142     cvm_module_fact_str(CVM_FACT_REALNAME, cvm_fact_realname);
143   cvm_module_fact_str(CVM_FACT_DIRECTORY, cvm_fact_directory);
144   if (cvm_fact_shell)
145     cvm_module_fact_str(CVM_FACT_SHELL, cvm_fact_shell);
146   if (cvm_fact_groupname)
147     cvm_module_fact_str(CVM_FACT_GROUPNAME, cvm_fact_groupname);
148   if (cvm_fact_sys_username)
149     cvm_module_fact_str(CVM_FACT_SYS_USERNAME, cvm_fact_sys_username);
150   if (cvm_fact_sys_directory)
151     cvm_module_fact_str(CVM_FACT_SYS_DIRECTORY, cvm_fact_sys_directory);
152   if (cvm_fact_domain)
153     cvm_module_fact_str(CVM_FACT_DOMAIN, cvm_fact_domain);
154   if (cvm_fact_mailbox)
155     cvm_module_fact_str(CVM_FACT_MAILBOX, cvm_fact_mailbox);
156   return 0;
157 }
158