Whamcloud - gitweb
LU-1201 checksum: add libcfs crypto hash
[fs/lustre-release.git] / lustre / obdfilter / filter_capa.c
index 1fbddb6..59cf195 100644 (file)
@@ -1,6 +1,4 @@
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
+/*
  * GPL HEADER START
  *
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -26,7 +24,7 @@
  * GPL HEADER END
  */
 /*
- * Copyright  2008 Sun Microsystems, Inc. All rights reserved
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  */
 /*
@@ -62,9 +60,9 @@ int filter_update_capa_key(struct obd_device *obd, struct lustre_capa_key *new)
         struct filter_capa_key *k, *keys[2] = { NULL, NULL };
         int i;
 
-        spin_lock(&capa_lock);
-        list_for_each_entry(k, &filter->fo_capa_keys, k_list) {
-                if (k->k_key.lk_mdsid != new->lk_mdsid)
+        cfs_spin_lock(&capa_lock);
+        cfs_list_for_each_entry(k, &filter->fo_capa_keys, k_list) {
+                if (k->k_key.lk_seq != new->lk_seq)
                         continue;
 
                 if (keys[0]) {
@@ -75,7 +73,7 @@ int filter_update_capa_key(struct obd_device *obd, struct lustre_capa_key *new)
                         keys[0] = k;
                 }
         }
-        spin_unlock(&capa_lock);
+        cfs_spin_unlock(&capa_lock);
 
         for (i = 0; i < 2; i++) {
                 if (!keys[i])
@@ -85,9 +83,9 @@ int filter_update_capa_key(struct obd_device *obd, struct lustre_capa_key *new)
                 /* maybe because of recovery or other reasons, MDS sent the
                  * the old capability key again.
                  */
-                spin_lock(&capa_lock);
+                cfs_spin_lock(&capa_lock);
                 keys[i]->k_key = *new;
-                spin_unlock(&capa_lock);
+                cfs_spin_unlock(&capa_lock);
 
                 RETURN(0);
         }
@@ -102,17 +100,17 @@ int filter_update_capa_key(struct obd_device *obd, struct lustre_capa_key *new)
                 CFS_INIT_LIST_HEAD(&k->k_list);
         }
 
-        spin_lock(&capa_lock);
+        cfs_spin_lock(&capa_lock);
         k->k_key = *new;
-        if (list_empty(&k->k_list))
-                list_add(&k->k_list, &filter->fo_capa_keys);
-        spin_unlock(&capa_lock);
+        if (cfs_list_empty(&k->k_list))
+                cfs_list_add(&k->k_list, &filter->fo_capa_keys);
+        cfs_spin_unlock(&capa_lock);
 
         DEBUG_CAPA_KEY(D_SEC, new, "new");
         RETURN(0);
 }
 
-int filter_auth_capa(struct obd_export *exp, struct lu_fid *fid, __u64 mdsid,
+int filter_auth_capa(struct obd_export *exp, struct lu_fid *fid, obd_seq seq,
                      struct lustre_capa *capa, __u64 opc)
 {
         struct obd_device *obd = exp->exp_obd;
@@ -124,19 +122,26 @@ int filter_auth_capa(struct obd_export *exp, struct lu_fid *fid, __u64 mdsid,
         int keys_ready = 0, key_found = 0, rc = 0;
         ENTRY;
 
+        /* skip capa check for llog and obdecho */
+        if (!fid_seq_is_mdt(seq))
+                RETURN(0);
+
         /* capability is disabled */
         if (!filter->fo_fl_oss_capa)
                 RETURN(0);
 
+        if (!(exp->exp_connect_flags & OBD_CONNECT_OSS_CAPA))
+                RETURN(0);
+
         if (capa == NULL) {
                 if (fid)
-                        CERROR("mdsno/fid/opc "LPU64"/"DFID"/"LPX64
+                        CERROR("seq/fid/opc "LPU64"/"DFID"/"LPX64
                                ": no capability has been passed\n",
-                               mdsid, PFID(fid), opc);
+                               seq, PFID(fid), opc);
                 else
-                        CERROR("mdsno/opc "LPU64"/"LPX64
+                        CERROR("seq/opc "LPU64"/"LPX64
                                ": no capability has been passed\n",
-                               mdsid, opc);
+                               seq, opc);
                 RETURN(-EACCES);
         }
 
@@ -153,20 +158,25 @@ int filter_auth_capa(struct obd_export *exp, struct lu_fid *fid, __u64 mdsid,
 
         oc = capa_lookup(filter->fo_capa_hash, capa, 0);
         if (oc) {
-                spin_lock(&oc->c_lock);
+                cfs_spin_lock(&oc->c_lock);
                 if (capa_is_expired(oc)) {
                         DEBUG_CAPA(D_ERROR, capa, "expired");
                         rc = -ESTALE;
                 }
-                spin_unlock(&oc->c_lock);
+                cfs_spin_unlock(&oc->c_lock);
 
                 capa_put(oc);
                 RETURN(rc);
         }
 
-        spin_lock(&capa_lock);
-        list_for_each_entry(k, &filter->fo_capa_keys, k_list)
-                if (k->k_key.lk_mdsid == mdsid) {
+        if (capa_is_expired_sec(capa)) {
+                DEBUG_CAPA(D_ERROR, capa, "expired");
+                RETURN(-ESTALE);
+        }
+
+        cfs_spin_lock(&capa_lock);
+        cfs_list_for_each_entry(k, &filter->fo_capa_keys, k_list) {
+                if (k->k_key.lk_seq == seq) {
                         keys_ready = 1;
                         if (k->k_key.lk_keyid == capa_keyid(capa)) {
                                 key = k->k_key;
@@ -174,7 +184,8 @@ int filter_auth_capa(struct obd_export *exp, struct lu_fid *fid, __u64 mdsid,
                                 break;
                         }
                 }
-        spin_unlock(&capa_lock);
+        }
+        cfs_spin_unlock(&capa_lock);
 
         if (!keys_ready) {
                 CDEBUG(D_SEC, "MDS hasn't propagated capability keys yet, "
@@ -212,14 +223,76 @@ int filter_auth_capa(struct obd_export *exp, struct lu_fid *fid, __u64 mdsid,
         RETURN(0);
 }
 
+int filter_capa_fixoa(struct obd_export *exp, struct obdo *oa, obd_seq seq,
+                      struct lustre_capa *capa)
+{
+        int rc = 0;
+        ENTRY;
+
+        /* skip capa check for llog and obdecho */
+        if (!fid_seq_is_mdt(seq))
+                RETURN(0);
+
+        if (!(exp->exp_connect_flags & OBD_CONNECT_OSS_CAPA))
+                RETURN(0);
+
+        if (unlikely(!capa))
+                RETURN(-EACCES);
+
+        if (capa_flags(capa) == LC_ID_CONVERT) {
+                struct obd_device *obd = exp->exp_obd;
+                struct filter_obd *filter = &obd->u.filter;
+                struct filter_capa_key *k;
+                int found = 0;
+
+                cfs_spin_lock(&capa_lock);
+                cfs_list_for_each_entry(k, &filter->fo_capa_keys, k_list) {
+                        if (k->k_key.lk_seq == seq &&
+                            k->k_key.lk_keyid == capa_keyid(capa)) {
+                                found = 1;
+                                break;
+                        }
+                }
+                cfs_spin_unlock(&capa_lock);
+
+                if (found) {
+                        union {
+                                __u64 id64;
+                                __u32 id32[2];
+                        } uid, gid;
+                        __u32 d[4], s[4];
+
+                        uid.id64 = capa_uid(capa);
+                        gid.id64 = capa_gid(capa);
+                        s[0] = uid.id32[0];
+                        s[1] = uid.id32[1];
+                        s[2] = gid.id32[0];
+                        s[3] = gid.id32[1];
+
+                        rc = capa_decrypt_id(d, s, k->k_key.lk_key,
+                                             CAPA_HMAC_KEY_MAX_LEN);
+                        if (unlikely(rc))
+                                RETURN(rc);
+
+                        oa->o_uid = d[0];
+                        oa->o_gid = d[2];
+                } else {
+                        DEBUG_CAPA(D_ERROR, capa, "no matched capability key for");
+                        rc = -ESTALE;
+                }
+        }
+
+        RETURN(rc);
+}
+
 void filter_free_capa_keys(struct filter_obd *filter)
 {
         struct filter_capa_key *key, *n;
 
-        spin_lock(&capa_lock);
-        list_for_each_entry_safe(key, n, &filter->fo_capa_keys, k_list) {
-                list_del_init(&key->k_list);
+        cfs_spin_lock(&capa_lock);
+        cfs_list_for_each_entry_safe(key, n, &filter->fo_capa_keys, k_list) {
+                cfs_list_del_init(&key->k_list);
                 OBD_FREE(key, sizeof(*key));
         }
-        spin_unlock(&capa_lock);
+        cfs_spin_unlock(&capa_lock);
 }