]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw, cls/otp: support for base32 seed type
authorYehuda Sadeh <yehuda@redhat.com>
Mon, 4 Dec 2017 13:42:51 +0000 (05:42 -0800)
committerYehuda Sadeh <yehuda@redhat.com>
Mon, 9 Apr 2018 14:02:17 +0000 (07:02 -0700)
Signed-off-by: Yehuda Sadeh <yehuda@redhat.com>
src/cls/otp/cls_otp.cc
src/cls/otp/cls_otp_types.cc
src/cls/otp/cls_otp_types.h
src/rgw/rgw_admin.cc

index 6da4934e801681e418daae6dc41d0be76604978d..b756f66b3c3e8e330ab801da48efba6dc472044b 100644 (file)
@@ -258,18 +258,35 @@ static int write_header(cls_method_context_t hctx, const otp_header& h)
   return 0;
 }
 
-static int parse_seed(const string& seed, bufferlist *seed_bin)
+static int parse_seed(const string& seed, SeedType seed_type, bufferlist *seed_bin)
 {
-  size_t slen = seed.size() / 2 + 1;
-  char secret[slen];
-  int result = oath_hex2bin(seed.c_str(), secret, &slen);
+  size_t slen = seed.length();
+  char secret[seed.length()];
+  char *psecret = secret;
+  int result;
+  bool need_free = false;
+
+  seed_bin->clear();
+
+  switch (seed_type) {
+    case OTP_SEED_BASE32:
+      need_free = true; /* oath_base32_decode allocates dest buffer */
+      result = oath_base32_decode(seed.c_str(), seed.length(),
+                                  &psecret, &slen);
+      break;
+    default: /* just assume hex is the default */
+      result = oath_hex2bin(seed.c_str(), psecret, &slen);
+  }
   if (result != OATH_OK) {
     CLS_LOG(20, "failed to parse seed");
     return -EINVAL;
   }
 
-  seed_bin->clear();
-  seed_bin->append(secret, slen);
+  seed_bin->append(psecret, slen);
+
+  if (need_free) {
+    free(psecret);
+  }
 
   return 0;
 }
@@ -302,7 +319,7 @@ static int otp_set_op(cls_method_context_t hctx,
     }
     instance.otp = entry;
 
-    r = parse_seed(instance.otp.seed, &instance.otp.seed_bin);
+    r = parse_seed(instance.otp.seed, instance.otp.seed_type, &instance.otp.seed_bin);
     if (r < 0) {
       return r;
     }
index 159b3604966cbd8fcb96345c23253ebf41aef124..b8a6e0125e4bbfb3d0d5e34092ea0f1d5139c192 100644 (file)
@@ -28,6 +28,18 @@ void otp_info_t::dump(Formatter *f) const
   encode_json("type", (int)type, f);
   encode_json("id", id, f);
   encode_json("seed", seed, f);
+  string st;
+  switch (seed_type) {
+    case rados::cls::otp::OTP_SEED_HEX:
+      st = "hex";
+      break;
+    case rados::cls::otp::OTP_SEED_BASE32:
+      st = "base32";
+      break;
+    default:
+      st = "unknown";
+  }
+  encode_json("seed_type", st, f);
   encode_json("time_ofs", time_ofs, f);
   encode_json("step_size", step_size, f);
   encode_json("window", window, f);
@@ -40,6 +52,15 @@ void otp_info_t::decode_json(JSONObj *obj)
   type = (OTPType)t;
   JSONDecoder::decode_json("id", id, obj);
   JSONDecoder::decode_json("seed", seed, obj);
+  string st;
+  JSONDecoder::decode_json("seed_type", st, obj);
+  if (st == "hex") {
+    seed_type = OTP_SEED_HEX;
+  } else if (st == "base32") {
+    seed_type = OTP_SEED_BASE32;
+  } else {
+    seed_type = OTP_SEED_UNKNOWN;
+  }
   JSONDecoder::decode_json("time_ofs", time_ofs, obj);
   JSONDecoder::decode_json("step_size", step_size, obj);
   JSONDecoder::decode_json("window", window, obj);
index b863e24fdbb2d073a36c23555e945864dfc29097..24f1f20948d154881440602c2695132a8565ce0e 100644 (file)
@@ -19,10 +19,17 @@ namespace rados {
         OTP_TOTP = 2,
       };
 
+      enum SeedType {
+        OTP_SEED_UNKNOWN = 0,
+        OTP_SEED_HEX = 1,
+        OTP_SEED_BASE32 = 2,
+      };
+
       struct otp_info_t {
         OTPType type{OTP_TOTP};
         string id;
         string seed;
+        SeedType seed_type{OTP_SEED_UNKNOWN};
         bufferlist seed_bin; /* parsed seed, built automatically by otp_set_op,
                               * not being json encoded/decoded on purpose
                               */
@@ -39,6 +46,7 @@ namespace rados {
            * then we'll need to branch here */
           ::encode(id, bl);
           ::encode(seed, bl);
+          ::encode((uint8_t)seed_type, bl);
           ::encode(seed_bin, bl);
           ::encode(time_ofs, bl);
           ::encode(step_size, bl);
@@ -52,6 +60,9 @@ namespace rados {
           type = (OTPType)t;
           ::decode(id, bl);
           ::decode(seed, bl);
+          uint8_t st;
+          ::decode(st, bl);
+          seed_type = (SeedType)st;
           ::decode(seed_bin, bl);
           ::decode(time_ofs, bl);
           ::decode(step_size, bl);
index 05c03058b4196efb0fe526ad119e0c6bdc94ee9d..bf0575969ca3a28483ccc598354be24d5816bae5 100644 (file)
@@ -2617,6 +2617,7 @@ int main(int argc, const char **argv)
 
   string totp_serial;
   string totp_seed;
+  string totp_seed_type = "hex";
   vector<string> totp_pin;
   int totp_seconds = 0;
   int totp_window = 0;
@@ -2948,6 +2949,8 @@ int main(int argc, const char **argv)
       totp_pin.push_back(val);
     } else if (ceph_argparse_witharg(args, i, &val, "--totp-seed", (char*)NULL)) {
       totp_seed = val;
+    } else if (ceph_argparse_witharg(args, i, &val, "--totp-seed-type", (char*)NULL)) {
+      totp_seed_type = val;
     } else if (ceph_argparse_witharg(args, i, &val, "--totp-seconds", (char*)NULL)) {
       totp_seconds = atoi(val.c_str());
     } else if (ceph_argparse_witharg(args, i, &val, "--totp-window", (char*)NULL)) {
@@ -7368,8 +7371,20 @@ next:
       return EINVAL;
     }
 
+
+    rados::cls::otp::SeedType seed_type;
+    if (totp_seed_type == "hex") {
+      seed_type = rados::cls::otp::OTP_SEED_HEX;
+    } else if (totp_seed_type == "base32") {
+      seed_type = rados::cls::otp::OTP_SEED_BASE32;
+    } else {
+      cerr << "ERROR: invalid seed type: " << totp_seed_type << std::endl;
+      return EINVAL;
+    }
+
     config.id = totp_serial;
     config.seed = totp_seed;
+    config.seed_type = seed_type;
 
     if (totp_seconds > 0) {
       config.step_size = totp_seconds;