blob: 89dcf08724f6879c058a01956336f5a615ddc9f4 [file] [log] [blame]
Don Newton379ae252019-04-01 12:17:06 -04001// Copyright (C) MongoDB, Inc. 2017-present.
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may
4// not use this file except in compliance with the License. You may obtain
5// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
7package auth
8
9import (
10 "context"
11 "crypto/md5"
12 "fmt"
13
14 "io"
15
16 "github.com/mongodb/mongo-go-driver/bson"
17 "github.com/mongodb/mongo-go-driver/x/bsonx"
18 "github.com/mongodb/mongo-go-driver/x/network/command"
19 "github.com/mongodb/mongo-go-driver/x/network/description"
20 "github.com/mongodb/mongo-go-driver/x/network/wiremessage"
21)
22
23// MONGODBCR is the mechanism name for MONGODB-CR.
24//
25// The MONGODB-CR authentication mechanism is deprecated in MongoDB 4.0.
26const MONGODBCR = "MONGODB-CR"
27
28func newMongoDBCRAuthenticator(cred *Cred) (Authenticator, error) {
29 return &MongoDBCRAuthenticator{
30 DB: cred.Source,
31 Username: cred.Username,
32 Password: cred.Password,
33 }, nil
34}
35
36// MongoDBCRAuthenticator uses the MONGODB-CR algorithm to authenticate a connection.
37//
38// The MONGODB-CR authentication mechanism is deprecated in MongoDB 4.0.
39type MongoDBCRAuthenticator struct {
40 DB string
41 Username string
42 Password string
43}
44
45// Auth authenticates the connection.
46//
47// The MONGODB-CR authentication mechanism is deprecated in MongoDB 4.0.
48func (a *MongoDBCRAuthenticator) Auth(ctx context.Context, desc description.Server, rw wiremessage.ReadWriter) error {
49
50 // Arbiters cannot be authenticated
51 if desc.Kind == description.RSArbiter {
52 return nil
53 }
54
55 db := a.DB
56 if db == "" {
57 db = defaultAuthDB
58 }
59
60 cmd := command.Read{DB: db, Command: bsonx.Doc{{"getnonce", bsonx.Int32(1)}}}
61 ssdesc := description.SelectedServer{Server: desc}
62 rdr, err := cmd.RoundTrip(ctx, ssdesc, rw)
63 if err != nil {
64 return newError(err, MONGODBCR)
65 }
66
67 var getNonceResult struct {
68 Nonce string `bson:"nonce"`
69 }
70
71 err = bson.Unmarshal(rdr, &getNonceResult)
72 if err != nil {
73 return newAuthError("unmarshal error", err)
74 }
75
76 cmd = command.Read{
77 DB: db,
78 Command: bsonx.Doc{
79 {"authenticate", bsonx.Int32(1)},
80 {"user", bsonx.String(a.Username)},
81 {"nonce", bsonx.String(getNonceResult.Nonce)},
82 {"key", bsonx.String(a.createKey(getNonceResult.Nonce))},
83 },
84 }
85 _, err = cmd.RoundTrip(ctx, ssdesc, rw)
86 if err != nil {
87 return newError(err, MONGODBCR)
88 }
89
90 return nil
91}
92
93func (a *MongoDBCRAuthenticator) createKey(nonce string) string {
94 h := md5.New()
95
96 _, _ = io.WriteString(h, nonce)
97 _, _ = io.WriteString(h, a.Username)
98 _, _ = io.WriteString(h, mongoPasswordDigest(a.Username, a.Password))
99 return fmt.Sprintf("%x", h.Sum(nil))
100}