在cl-mongo中实现MongoDB SASL身份验证

时间:2015-09-09 18:15:14

标签: mongodb cryptography common-lisp sasl-scram

我已经从fons分叉了cl-mongo(常见的lisp MongoDB库)存储库,因为它已经不再需要维护,也不支持SCRAM-SHA-1登录过程。这是我的分支:https://github.com/mprelude/cl-mongo - 主要的变化是添加了对cl-scram(我的SCRAM实现)的依赖,并添加了一个bson二进制通用容器。

我仍在尝试发送初始邮件,因此问题不在于密码错误,因为尚未使用。

为什么这部分身份验证失败了?任何人都可以确认,如果我希望将MESSAGE中的内容传送给mongo,那么BINARY-MESSAGE是否应该发送给我?

这是我的电话,增加了一些调试输出:

* (asdf:load-system :cl-mongo)

T
* (cl-mongo:db.use "test")

"test"
* (cl-mongo:db.auth "aurumrw" "pencil" :mechanism :SCRAM-SHA-1)

(kv-container : #(#S(CL-MONGO::PAIR :KEY saslStart :VALUE 1)
                  #S(CL-MONGO::PAIR :KEY mechanism :VALUE SCRAM-SHA-1)
                  #S(CL-MONGO::PAIR
                     :KEY payload
                     :VALUE [CL-MONGO::BSON-BINARY-GENERIC]  [binary data of type 0] ))
 ((CL-MONGO::BINARY-MESSAGE
   . #(98 105 119 115 98 106 49 104 100 88 74 49 98 88 74 51 76 72 73 57 83 87
       116 122 101 84 100 78 101 71 100 97 90 71 52 53 85 69 86 113 87 108 104
       85 89 108 78 75 89 106 74 80 79 87 78 84 99 49 108 84 82 68 99 61))
  (CL-MONGO::MESSAGE . "n,,n=aurumrw,r=Iksy7MxgZdn9PEjZXTbSJb2O9cSsYSD7")
  (CL-MONGO::CODE . 18) (CL-MONGO::OK . 0.0d0)
  (CL-MONGO::ERRMSG . "Authentication failed.")))

值得注意的是,我认为Mongo必须正确阅读我的请求,因为消息是'身份验证失败' (错误代码18),这表明它理解我已经请求了SASL会话。

我认为我遇到的问题是基于有效负载,内容(base64' d初始消息,作为八位字节)或格式。

借鉴MongoDB documentation以及原始讨论的工作方式,这是我重写的db.auth函数:

(defmethod db.auth ((username string) (password string) &key (mongo (mongo)) (mechanism :SCRAM-SHA-1))
  (cond ((equal mechanism :SCRAM-SHA-1)
          ;; SCRAM-SHA-1 Login
          (let* ((nonce (cl-scram:gen-client-nonce))
                 (pwd (concatenate 'string username ":mongo:" password))
                 (md5-pwd (hex-md5 pwd))
                 (md5-pwd-str (ironclad:byte-array-to-hex-string md5-pwd))
                 (initial-message (cl-scram:gen-client-initial-message :username username
                                                                       :nonce nonce))
                 (request (kv (kv "saslStart" 1)
                              (kv "mechanism" "SCRAM-SHA-1")
                              (kv "payload"
                                  (bson-binary :generic (ironclad:ascii-string-to-byte-array
                                                          (cl-scram:base64-encode initial-message))))))
                 (response (car (docs (db.find "$cmd" request :limit 1 :mongo mongo))))
                 (retval (pairlis '(errmsg ok code message binary-message)
                                   (list (get-element "errmsg" response)
                                         (get-element "ok" response)
                                         (get-element "code" response)
                                         initial-message
                                         (ironclad:ascii-string-to-byte-array (cl-scram:base64-encode initial-message))))))
            (list request retval)))
        ((equal mechanism :MONGODB-CR)
          ;; MONGODB-CR Login.
          (let* ((nonce (get-element "nonce" (car (docs (db.run-command 'getnonce :mongo mongo)))))
                 (pwd (concatenate 'string username ":mongo:" password))
                 (md5-pwd (hex-md5 pwd))
                 (md5-pwd-str (ironclad:byte-array-to-hex-string md5-pwd))
                 (md5-key (hex-md5 (concatenate 'string nonce username md5-pwd-str)))
                 (md5-key-str (ironclad:byte-array-to-hex-string md5-key))
                 (request (kv (kv "authenticate" 1)
                              (kv "user" username)
                              (kv "nonce" nonce)
                              (kv "key" md5-key-str)))
                 (retval (get-element "ok" (car (docs (db.find "$cmd" request :limit 1 :mongo mongo))))))
            (if retval t nil)))
        (t nil)))

1 个答案:

答案 0 :(得分:0)

从我们连接到mongo服务器的位置检查客户端的mongo版本(mongo --version)。

我的情况是,mongo服务器的版本为Mongo4.0.0,但我的客户端的版本为2.4.9。更新mongo版本以更新mongo cli。