func main() { l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", LdapServer, LdapPort)) if err != nil { log.Fatalf("ERROR: %s\n", err.Error()) } defer l.Close() // l.Debug = true l.Bind(BindDN, BindPW) log.Printf("The Search for Kirk ... %s\n", Filter) entry, err := search(l, Filter, []string{}) if err != nil { log.Fatal("could not get entry") } entry.PrettyPrint(0) log.Printf("modify the mail address and add a description ... \n") modify := ldap.NewModifyRequest(entry.DN) modify.Add("description", []string{"Captain of the USS Enterprise"}) modify.Replace("mail", []string{"*****@*****.**"}) if err := l.Modify(modify); err != nil { log.Fatalf("ERROR: %s\n", err.Error()) } entry, err = search(l, Filter, []string{}) if err != nil { log.Fatal("could not get entry") } entry.PrettyPrint(0) log.Printf("reset the entry ... \n") modify = ldap.NewModifyRequest(entry.DN) modify.Delete("description", []string{}) modify.Replace("mail", []string{"*****@*****.**"}) if err := l.Modify(modify); err != nil { log.Fatalf("ERROR: %s\n", err.Error()) } entry, err = search(l, Filter, []string{}) if err != nil { log.Fatal("could not get entry") } entry.PrettyPrint(0) }
/* HandleServerRequest handles the flow for messages that this server accepts from clients. */ func (sm *server) HandleServerRequest(m protocol.MessageReadWriteCloser, r *protocol.ServerRequest) { if assumeRoleMsg := r.GetAssumeRole(); assumeRoleMsg != nil { log.Debug("Handling an assumeRole request.") sm.stats.Counter(1.0, "messages.assumeRole", 1) role := assumeRoleMsg.GetRole() user, err := sm.SSHChallenge(m) if err != nil { log.Errorf("Error trying to handle AssumeRole: %s", err.Error()) m.Close() return } if user != nil { creds, err := sm.credentials.AssumeRole(user, role, sm.enableLDAPRoles) if err != nil { // error message from Amazon, so forward that on to the client errStr := err.Error() errMsg := &protocol.Message{ Error: &errStr, } log.Errorf("Error from AWS for AssumeRole: %s", err.Error()) m.Write(errMsg) sm.stats.Counter(1.0, "errors.assumeRole", 1) //m.Close() return } m.Write(makeCredsResponse(creds)) return } } else if getUserCredentialsMsg := r.GetGetUserCredentials(); getUserCredentialsMsg != nil { sm.stats.Counter(1.0, "messages.getUserCredentialsMsg", 1) user, err := sm.SSHChallenge(m) if err != nil { log.Errorf("Error trying to handle GetUserCredentials: %s", err.Error()) m.Close() return } if user != nil { creds, err := sm.credentials.AssumeRole(user, sm.DefaultRole, sm.enableLDAPRoles) if err != nil { log.Errorf("Error trying to handle GetUserCredentials: %s", err.Error()) m.Close() return } m.Write(makeCredsResponse(creds)) return } } else if addSSHKeyMsg := r.GetAddSSHkey(); addSSHKeyMsg != nil { sm.stats.Counter(1.0, "messages.addSSHKeyMsg", 1) // Search for the user specified in this request. sr := ldap.NewSearchRequest( sm.baseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, fmt.Sprintf("(%s=%s)", sm.userAttr, addSSHKeyMsg.GetUsername()), []string{"sshPublicKey", sm.userAttr, "userPassword"}, nil) user, err := sm.ldapServer.Search(sr) if err != nil { log.Errorf("Error trying to handle addSSHKeyMsg: %s", err.Error()) return } if len(user.Entries) == 0 { log.Errorf("User %s not found!", addSSHKeyMsg.GetUsername()) return } // Check their password. password := user.Entries[0].GetAttributeValue("userPassword") if password != addSSHKeyMsg.GetPasswordhash() { log.Errorf("Provided password for user %s does not match %s!", addSSHKeyMsg.GetUsername(), password) return } // Check to see if this SSH key already exists. for _, k := range user.Entries[0].GetAttributeValues("sshPublicKey") { if k == addSSHKeyMsg.GetSshkeybytes() { log.Warning("User %s already has this SSH key. Doing nothing.", addSSHKeyMsg.GetUsername()) successMsg := &protocol.Message{Success: &protocol.Success{}} m.Write(successMsg) return } } mr := ldap.NewModifyRequest(user.Entries[0].DN) mr.Add("sshPublicKey", []string{addSSHKeyMsg.GetSshkeybytes()}) err = sm.ldapServer.Modify(mr) if err != nil { log.Errorf("Could not modify LDAP user: %s", err.Error()) return } successMsg := &protocol.Message{Success: &protocol.Success{}} m.Write(successMsg) return } }
func TestServerStateMachine(t *testing.T) { // This silly thing is needed for equality testing for the LDAP dummy. neededModifyRequest := ldap.NewModifyRequest("something") neededModifyRequest.Add("sshPublicKey", []string{"test"}) Convey("Given a state machine setup with a null logger", t, func() { authenticator := &DummyAuthenticator{&server.User{Username: "******"}} ldap := &DummyLDAP{ username: "******", password: "******", sshKeys: []string{}, req: neededModifyRequest, } testServer := server.New(authenticator, &dummyCredentials{}, "default", g2s.Noop(), ldap, "cn", "dc=testdn,dc=com", false) r, w := io.Pipe() testConnection := protocol.NewMessageConnection(ReadWriter(r, w)) go testServer.HandleConnection(testConnection) Convey("When a ping message comes in", func() { testPing := &protocol.Message{Ping: &protocol.Ping{}} testConnection.Write(testPing) Convey("Then the server should respond with a pong response.", func() { recvMsg, recvErr := testConnection.Read() So(recvErr, ShouldBeNil) So(recvMsg.GetPing(), ShouldNotBeNil) }) }) Convey("After an AssumeRequest", func() { role := "testrole" msg := &protocol.Message{ ServerRequest: &protocol.ServerRequest{ AssumeRole: &protocol.AssumeRole{ Role: &role, }, }, } testConnection.Write(msg) msg, err := testConnection.Read() if err != nil { t.Fatal(err) } Convey("it should challenge, then send credentials on success", func() { challenge := msg.GetServerResponse().GetChallenge().GetChallenge() So(len(challenge), ShouldEqual, 64) format := "test" sig := []byte("ssss") challengeResponseMsg := &protocol.Message{ ServerRequest: &protocol.ServerRequest{ ChallengeResponse: &protocol.SSHChallengeResponse{ Format: &format, Signature: sig, }, }, } testConnection.Write(challengeResponseMsg) credsMsg, err := testConnection.Read() if err != nil { t.Fatal(err) } So(credsMsg, ShouldNotBeNil) So(credsMsg.GetServerResponse(), ShouldNotBeNil) So(credsMsg.GetServerResponse().GetCredentials(), ShouldNotBeNil) creds := credsMsg.GetServerResponse().GetCredentials() So(creds.GetAccessKeyId(), ShouldEqual, "access_key") So(creds.GetSecretAccessKey(), ShouldEqual, "secret") So(creds.GetAccessToken(), ShouldEqual, "token") So(creds.GetExpiration(), ShouldBeGreaterThanOrEqualTo, time.Now().Unix()) }) Convey("it should then send failure message on failed key verification", func() { authenticator.user = nil challenge := msg.GetServerResponse().GetChallenge().GetChallenge() So(len(challenge), ShouldEqual, 64) format := "test" sig := []byte("ssss") challengeResponseMsg := &protocol.Message{ ServerRequest: &protocol.ServerRequest{ ChallengeResponse: &protocol.SSHChallengeResponse{ Format: &format, Signature: sig, }, }, } testConnection.Write(challengeResponseMsg) credsMsg, err := testConnection.Read() if err != nil { t.Fatal(err) } So(credsMsg, ShouldNotBeNil) So(credsMsg.GetServerResponse(), ShouldNotBeNil) So(credsMsg.GetServerResponse().GetVerificationFailure(), ShouldNotBeNil) }) }) Convey("When a request to add an SSH key comes in", func() { user := "******" password := "******" sshKey := "test" testMessage := &protocol.Message{ ServerRequest: &protocol.ServerRequest{ AddSSHkey: &protocol.AddSSHKey{ Username: &user, Passwordhash: &password, Sshkeybytes: &sshKey, }, }, } testConnection.Write(testMessage) Convey("If this request is valid", func() { msg, err := testConnection.Read() if err != nil { t.Fatal(err) } if msg.GetSuccess() == nil { t.Fail() } Convey("It should add the SSH key to the user.", func() { So(ldap.sshKeys[0], ShouldEqual, sshKey) Convey("If the user tries to add the same SSH key", func() { testConnection.Write(testMessage) Convey("It should not insert the same key twice.", func() { So(len(ldap.sshKeys), ShouldEqual, 1) }) }) }) }) }) }) }