Whamcloud - gitweb
Branch: HEAD
[fs/lustre-release.git] / lustre / sec / gks / gks_server.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * lustre GS server
5  *  Copyright (c) 2001-2003 Cluster File Systems, Inc.
6  *
7  *   This file is part of Lustre, http://www.lustre.org.
8  *
9  *   Lustre is free software; you can redistribute it and/or
10  *   modify it under the terms of version 2 of the GNU General Public
11  *   License as published by the Free Software Foundation.
12  *
13  *   Lustre is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *   GNU General Public License for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with Lustre; if not, write to the Free Software
20  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22 #ifndef EXPORT_SYMTAB
23 # define EXPORT_SYMTAB
24 #endif
25 #define DEBUG_SUBSYSTEM S_GKS
26
27 #include <linux/module.h>
28 #include <linux/crypto.h>
29 #include <linux/random.h>
30 #include <linux/init.h>
31 #include <linux/obd_class.h>
32 #include <linux/lustre_gs.h>
33
34 #include "gks_internal.h"
35
36 #define GKS_KEY "19760218"
37 #define GKS_KEY_LEN 8 
38 #define GKS_MAC_ALG "sha1"
39 #define GKS_KEY_ALG "des"
40 #define GKS_KEY_ALG_MODE CRYPTO_TFM_MODE_CBC
41
42 static int gks_cleanup(struct obd_device *obd, int flags)
43 {
44         struct gks_obd *gks = &obd->u.gks;
45         ENTRY;     
46
47         if (gks->gks_mac_tfm) {
48                 crypto_free_tfm(gks->gks_mac_tfm);
49         }
50         if (gks->gks_key.key) {
51                 OBD_FREE(gks->gks_key.key, gks->gks_key.len);
52         }  
53         if (gks->gks_key_tfm) {
54                 crypto_free_tfm(gks->gks_key_tfm);
55         }
56
57         RETURN(0);
58 }
59
60 static int gks_setup(struct obd_device *obd, obd_count len, void *buf)
61 {
62         struct gks_obd *gks = &obd->u.gks;
63         int rc = 0;
64
65         gks->gks_mac_tfm = crypto_alloc_tfm(GKS_MAC_ALG, 0);
66         if (!gks->gks_mac_tfm)
67                 RETURN(-ENOSYS);
68         /*Now: we only keep an unchanged key in the whole system*/
69         gks->gks_key.len = GKS_KEY_LEN;
70         
71         OBD_ALLOC(gks->gks_key.key, GKS_KEY_LEN);
72
73         LASSERT(gks->gks_key.key);
74         
75         memcpy(gks->gks_key.key, GKS_KEY, GKS_KEY_LEN); 
76         /*set gks cipher type*/
77
78         gks->gks_key_tfm = crypto_alloc_tfm(GKS_KEY_ALG, GKS_KEY_ALG_MODE);
79         if (!gks->gks_key_tfm)
80                 GOTO(out, rc = -ENOSYS);                
81         if (crypto_cipher_setkey(gks->gks_key_tfm, gks->gks_key.key, 
82                                  gks->gks_key.len))
83                 GOTO(out, rc = -ENOSYS);
84 out:
85         if (rc) {
86                 gks_cleanup(obd, 0);
87         }
88         RETURN(rc);
89 }
90
91 static int gks_connect(struct lustre_handle *conn, struct obd_device *obd,
92                        struct obd_uuid *cluuid, struct obd_connect_data *data,
93                        unsigned long flags)
94 {
95         int rc;
96         ENTRY;
97
98         if (!conn || !obd || !cluuid)
99                 RETURN(-EINVAL);
100
101         rc = class_connect(conn, obd, cluuid);
102
103         RETURN(rc);
104 }
105
106 static int gks_disconnect(struct obd_export *exp, unsigned long flags)
107 {
108         int rc = 0;
109         ENTRY;
110
111         rc = class_disconnect(exp, flags);
112         
113         target_destroy_export(exp);
114         
115         RETURN(rc);
116 }
117
118 static int gks_msg_check_version(struct lustre_msg *msg)
119 {
120         int rc = 0;
121         ENTRY;
122
123         switch (msg->opc) {
124         case GKS_CONNECT:
125         case GKS_DISCONNECT:
126                 rc = lustre_msg_check_version(msg, LUSTRE_OBD_VERSION);
127                 if (rc)
128                         CERROR("bad opc %u version %08x, expecting %08x\n",
129                                msg->opc, msg->version, LUSTRE_OBD_VERSION);
130                 break;
131         case GKS_GET_KEY:
132         case GKS_DECRYPT_KEY:
133         case GKS_GET_MAC:
134                 rc = lustre_msg_check_version(msg, LUSTRE_GKS_VERSION);
135                 if (rc)
136                         CERROR("bad opc %u version %08x, expecting %08x\n",
137                                msg->opc, msg->version, LUSTRE_GKS_VERSION);
138                 break;
139         default:
140                 CERROR("GKS unknown opcode %d\n", msg->opc);
141                 rc = -ENOTSUPP;
142                 break;
143         }
144
145         RETURN(rc);
146 }
147
148 static int crypto_get_gks_mac(struct ptlrpc_request *req, 
149                               struct key_perm *kperm, 
150                               __u8 *hmac)
151 {
152         struct obd_device *obd = req->rq_export->exp_obd;
153         struct gks_obd *gks = &obd->u.gks;
154         int perm_size = crypto_kperm_size(kperm->kp_acl_count);
155         struct scatterlist sl = {
156                 .page   = virt_to_page(kperm),
157                 .offset = (unsigned long)(kperm) % PAGE_SIZE,
158                 .length = perm_size 
159         };
160         __u8 *key = gks->gks_key.key; 
161         int keylen = gks->gks_key.len;
162         struct crypto_tfm *tfm = gks->gks_mac_tfm;
163
164         ENTRY;
165         LASSERT(tfm);
166         
167         crypto_hmac(tfm, key, &keylen, &sl, 1, hmac);
168        
169         CDEBUG(D_INFO, "compute mac mac %s by uid %d gid %d" 
170                "mode %d acl_count %d acl %p perm_size %d\n",
171                hmac, kperm->kp_uid, kperm->kp_gid, kperm->kp_mode, 
172                kperm->kp_acl_count, kperm->kp_acls, perm_size);
173         
174         RETURN(0); 
175 }
176 #define crypto_decrypt_gks_key(req, data, len) \
177 crypto_crypt_gks_key(req, data, len, DECRYPT_DATA)
178
179 #define crypto_encrypt_gks_key(req, data, len) \
180 crypto_crypt_gks_key(req, data, len, ENCRYPT_DATA)
181
182 static int crypto_crypt_gks_key(struct ptlrpc_request *req, 
183                                 __u8 *data, int len, int mode) 
184 {
185         struct obd_device *obd = req->rq_export->exp_obd;
186         struct gks_obd *gks = &obd->u.gks;
187         struct scatterlist sl = {
188                 .page   = virt_to_page(data),
189                 .offset = (unsigned long)(data) % PAGE_SIZE,
190                 .length = len 
191         };
192         struct crypto_tfm *tfm = gks->gks_key_tfm;
193         __u8 local_iv[16] = {0};
194
195         ENTRY;
196         LASSERT(tfm);
197        
198         if (mode == ENCRYPT_DATA) 
199                 crypto_cipher_encrypt_iv(tfm, &sl, &sl, (unsigned int)len, 
200                                          local_iv);
201         else
202                 crypto_cipher_decrypt_iv(tfm, &sl, &sl, (unsigned int)len, 
203                                          local_iv);
204  
205         RETURN(0); 
206 }
207
208 static int gks_create_key(struct ptlrpc_request *req, int offset)
209 {
210         struct key_context *kctxt;
211         struct crypto_key  *ckey;
212
213         kctxt = lustre_swab_reqbuf(req, offset, sizeof (*kctxt),
214                                    lustre_swab_key_context);
215      
216         ckey = (struct crypto_key *)lustre_msg_buf(req->rq_repmsg, 0, 
217                                                    sizeof (*ckey));
218         
219         crypto_get_gks_mac(req, &kctxt->kc_perm, ckey->ck_mac);
220
221         CDEBUG(D_INFO, "compute mac mac %s by uid %d gid %d mode %d \n",
222                ckey->ck_mac, kctxt->kc_perm.kp_uid, kctxt->kc_perm.kp_gid,
223                kctxt->kc_perm.kp_mode);
224        
225         get_random_bytes(ckey->ck_key, KEY_SIZE);        
226         
227         ckey->ck_type = GKS_TYPE;
228         
229         CDEBUG(D_INFO, "get key %s\n", ckey->ck_key);
230
231         crypto_encrypt_gks_key(req, ckey->ck_key, KEY_SIZE);
232
233         CDEBUG(D_INFO, "encrypt key %s\n", ckey->ck_key);
234         
235         RETURN(0); 
236 }
237
238 static int gks_mac_verification(struct ptlrpc_request *req, 
239                                 struct crypto_key *key, 
240                                 struct key_perm *kperm)
241 {
242         __u8 *tmp_mac;
243         ENTRY;
244
245         OBD_ALLOC(tmp_mac, MAC_SIZE);
246
247         crypto_get_gks_mac(req, kperm, tmp_mac);
248
249         if (!memcmp(tmp_mac, key->ck_mac, MAC_SIZE)) {
250                 OBD_FREE(tmp_mac, MAC_SIZE);
251                 RETURN(0); 
252         }
253         CERROR("new_created %s EA is %s \n", tmp_mac, key->ck_mac);
254         OBD_FREE(tmp_mac, MAC_SIZE);
255         RETURN(-EPERM);
256 }
257
258 static int gks_permission_check(struct key_context *kctxt,
259                                 struct key_perm *kperm)
260 {
261         RETURN(0); 
262 }
263
264 static int gks_decrypt_key(struct ptlrpc_request *req, int offset)
265 {
266         struct key_context *kctxt;
267         struct key_perm    *kperm;
268         struct crypto_key  *ckey;
269         int                rc = 0;
270
271         kctxt = lustre_swab_reqbuf(req, offset, sizeof(*kctxt),
272                                    lustre_swab_key_context);
273         
274         /*authiticating the ops of the mac*/
275         rc = gks_mac_verification(req, &kctxt->kc_ck, &kctxt->kc_perm);
276         if (rc != 0) {
277                 CERROR("Not my authorization mac %s\n", kctxt->kc_ck.ck_mac);
278                 RETURN(rc);
279         }
280
281         kperm = lustre_swab_reqbuf(req, offset + 1, sizeof(*kperm),
282                                    lustre_swab_key_perms);
283
284         rc = gks_permission_check(kctxt, kperm);
285         if (rc != 0) {
286                 CERROR("permssion check failed\n");
287                 RETURN(rc);
288         }
289         ckey = (struct crypto_key *)lustre_msg_buf(req->rq_repmsg, 0, 
290                                                    sizeof (*ckey));
291         memcpy(ckey, &kctxt->kc_ck, sizeof(*ckey));
292
293         rc = crypto_decrypt_gks_key(req, ckey->ck_key, KEY_SIZE);
294         if (rc != 0) {
295                 CERROR("permssion check failed\n");
296                 RETURN(rc);
297         }
298         
299         RETURN(0); 
300 }
301
302 static int gks_get_mac(struct ptlrpc_request *req, int offset)
303 {
304         struct key_context *kctxt;
305         struct key_perm    *kperm;
306         struct crypto_key  *ckey;
307         int                rc = 0;
308
309         kctxt = lustre_swab_reqbuf(req, offset, sizeof(*kctxt),
310                                    lustre_swab_key_context);
311         
312         /*authiticating the ops of the mac*/
313         rc = gks_mac_verification(req, &kctxt->kc_ck, &kctxt->kc_perm);
314         if (rc != 0) {
315                 CERROR("Not my authorization mac %s\n", kctxt->kc_ck.ck_mac);
316                 RETURN(rc);
317         }
318
319         kperm = lustre_swab_reqbuf(req, offset + 1, sizeof(*kperm),
320                                    lustre_swab_key_perms);
321
322         rc = gks_permission_check(kctxt, kperm);
323         if (rc != 0) {
324                 CERROR("permssion check failed\n");
325                 RETURN(rc);
326         }
327         ckey = (struct crypto_key *)lustre_msg_buf(req->rq_repmsg, 0, 
328                                                    sizeof (*ckey));
329
330         memcpy(ckey, &kctxt->kc_ck, sizeof(*ckey));
331
332         ckey->ck_type = GKS_TYPE;
333         rc = crypto_get_gks_mac(req, kperm, ckey->ck_mac);
334         if (rc != 0) {
335                 CERROR("get new mac error %d \n", rc);
336                 RETURN(rc);
337         }
338
339         RETURN(rc);
340 }
341
342 int gks_handle(struct ptlrpc_request *req)
343 {
344         int fail = OBD_FAIL_MDS_ALL_REPLY_NET;
345         int rc;
346         ENTRY;
347
348         rc = gks_msg_check_version(req->rq_reqmsg);
349         if (rc) {
350                 CERROR("GKS drop mal-formed request\n");
351                 RETURN(rc);
352         }
353         switch (req->rq_reqmsg->opc) {
354         case GKS_CONNECT:
355                 DEBUG_REQ(D_INODE, req, "connect");
356                 rc = target_handle_connect(req);
357                 req->rq_status = rc;            /* superfluous? */
358                 break;
359         case GKS_DISCONNECT:
360                 DEBUG_REQ(D_INODE, req, "disconnect");
361                 rc = target_handle_disconnect(req);
362                 req->rq_status = rc;            /* superfluous? */
363                 break;
364
365         case GKS_GET_KEY: {
366                 int size[1] = {sizeof(struct crypto_key)};
367                 int bufcount = 1;
368  
369                 DEBUG_REQ(D_INODE, req, "get_key");
370                 lustre_pack_reply(req, bufcount, size, NULL);
371                 rc = gks_create_key(req, MDS_REQ_REC_OFF);      
372                 req->rq_status = rc;            /* superfluous? */
373                 break;     
374         }  
375         case GKS_DECRYPT_KEY: {
376                 int size[1] = {sizeof(struct crypto_key)};
377                 int bufcount = 1;
378  
379                 DEBUG_REQ(D_INODE, req, "decrypt_key");
380                 lustre_pack_reply(req, bufcount, size, NULL);
381                 rc = gks_decrypt_key(req, MDS_REQ_REC_OFF);      
382                 req->rq_status = rc;            /* superfluous? */
383                 break;     
384         }  
385         case GKS_GET_MAC: {
386                 int size[1] = {sizeof(struct crypto_key)};
387                 int bufcount = 1;
388                   
389                 DEBUG_REQ(D_INODE, req, "get_mac");
390                 lustre_pack_reply(req, bufcount, size, NULL);
391                 rc = gks_get_mac(req, MDS_REQ_REC_OFF);      
392                 req->rq_status = rc;            /* superfluous? */
393                 break;
394         }
395         default:
396                 req->rq_status = -ENOTSUPP;
397                 rc = ptlrpc_error(req);
398                 RETURN(rc);
399         } 
400         target_send_reply(req, rc, fail);
401         RETURN(rc);
402 }
403
404 static int gkt_setup(struct obd_device *obd, obd_count len, void *buf)
405 {
406         struct gks_obd *gks = &obd->u.gks;
407         int rc = 0;
408         ENTRY;
409
410         gks->gks_service =
411                 ptlrpc_init_svc(GKS_NBUFS, GKS_BUFSIZE, GKS_MAXREQSIZE,
412                                 GKS_REQUEST_PORTAL, GKC_REPLY_PORTAL,
413                                 GKS_SERVICE_WATCHDOG_TIMEOUT,
414                                 gks_handle, "gks", obd->obd_proc_entry);
415         if (!gks->gks_service) {
416                 CERROR("failed to start service\n");
417                 RETURN(-ENOMEM);
418         }
419
420         rc = ptlrpc_start_n_threads(obd, gks->gks_service, GKT_NUM_THREADS,
421                                     "ll_gkt");
422         
423         RETURN(rc);
424 }
425
426 static int gkt_cleanup(struct obd_device *obd, int flags)
427 {
428         struct gks_obd *gks = &obd->u.gks;
429
430         ptlrpc_stop_all_threads(gks->gks_service);
431         ptlrpc_unregister_service(gks->gks_service);
432         RETURN(0);
433 }
434
435 int gks_attach(struct obd_device *dev, obd_count len, void *data)
436 {
437         struct lprocfs_static_vars lvars;
438
439         lprocfs_init_vars(gks, &lvars);
440         return lprocfs_obd_attach(dev, lvars.obd_vars);
441 }
442
443 int gks_detach(struct obd_device *dev)
444 {
445         return lprocfs_obd_detach(dev);
446 }
447
448 int gkt_attach(struct obd_device *dev, obd_count len, void *data)
449 {
450         struct lprocfs_static_vars lvars;
451
452         lprocfs_init_vars(gkt, &lvars);
453         return lprocfs_obd_attach(dev, lvars.obd_vars);
454 }
455
456 int gkt_detach(struct obd_device *dev)
457 {
458         return lprocfs_obd_detach(dev);
459 }
460
461 static struct obd_ops gks_obd_ops = {
462         .o_owner           = THIS_MODULE,
463         .o_attach          = gks_attach,
464         .o_detach          = gks_detach,
465         .o_setup           = gks_setup,
466         .o_cleanup         = gks_cleanup,
467         .o_connect         = gks_connect,
468         .o_disconnect         = gks_disconnect,
469 };
470
471 static struct obd_ops gkt_obd_ops = {
472         .o_owner           = THIS_MODULE,
473         .o_attach          = gkt_attach,
474         .o_detach          = gkt_detach,
475         .o_setup           = gkt_setup,
476         .o_cleanup         = gkt_cleanup,
477 };
478
479 static int __init gks_init(void)
480 {
481         struct lprocfs_static_vars lvars;
482
483         lprocfs_init_vars(gks, &lvars);
484         class_register_type(&gks_obd_ops, NULL, lvars.module_vars,
485                             LUSTRE_GKS_NAME);
486         
487         lprocfs_init_vars(gkt, &lvars);
488         class_register_type(&gkt_obd_ops, NULL, lvars.module_vars,
489                             LUSTRE_GKT_NAME);
490         RETURN(0);
491 }
492
493 static void gks_exit(void)
494 {
495         class_unregister_type(LUSTRE_GKS_NAME);
496         class_unregister_type(LUSTRE_GKT_NAME);
497 }
498
499 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
500 MODULE_DESCRIPTION("Lustre GS Server (GS)");
501 MODULE_LICENSE("GPL");
502
503 module_init(gks_init);
504 module_exit(gks_exit);
505