|
@@ -1029,6 +1029,18 @@ func (am *AccountManager) checkPassphrase(accountName, passphrase string) (accou
|
1029
|
1029
|
return
|
1030
|
1030
|
}
|
1031
|
1031
|
|
|
1032
|
+func (am *AccountManager) loadWithAutocreation(accountName string, autocreate bool) (account ClientAccount, err error) {
|
|
1033
|
+ account, err = am.LoadAccount(accountName)
|
|
1034
|
+ if err == errAccountDoesNotExist && autocreate {
|
|
1035
|
+ err = am.SARegister(accountName, "")
|
|
1036
|
+ if err != nil {
|
|
1037
|
+ return
|
|
1038
|
+ }
|
|
1039
|
+ account, err = am.LoadAccount(accountName)
|
|
1040
|
+ }
|
|
1041
|
+ return
|
|
1042
|
+}
|
|
1043
|
+
|
1032
|
1044
|
func (am *AccountManager) AuthenticateByPassphrase(client *Client, accountName string, passphrase string) (err error) {
|
1033
|
1045
|
// XXX check this now, so we don't allow a redundant login for an always-on client
|
1034
|
1046
|
// even for a brief period. the other potential source of nick-account conflicts
|
|
@@ -1048,19 +1060,29 @@ func (am *AccountManager) AuthenticateByPassphrase(client *Client, accountName s
|
1048
|
1060
|
}
|
1049
|
1061
|
}()
|
1050
|
1062
|
|
1051
|
|
- ldapConf := am.server.Config().Accounts.LDAP
|
1052
|
|
- if ldapConf.Enabled {
|
|
1063
|
+ config := am.server.Config()
|
|
1064
|
+ if config.Accounts.LDAP.Enabled {
|
|
1065
|
+ ldapConf := am.server.Config().Accounts.LDAP
|
1053
|
1066
|
err = ldap.CheckLDAPPassphrase(ldapConf, accountName, passphrase, am.server.logger)
|
1054
|
|
- if err == nil {
|
1055
|
|
- account, err = am.LoadAccount(accountName)
|
1056
|
|
- // autocreate if necessary:
|
1057
|
|
- if err == errAccountDoesNotExist && ldapConf.Autocreate {
|
1058
|
|
- err = am.SARegister(accountName, "")
|
1059
|
|
- if err != nil {
|
1060
|
|
- return
|
1061
|
|
- }
|
1062
|
|
- account, err = am.LoadAccount(accountName)
|
|
1067
|
+ if err != nil {
|
|
1068
|
+ account, err = am.loadWithAutocreation(accountName, ldapConf.Autocreate)
|
|
1069
|
+ return
|
|
1070
|
+ }
|
|
1071
|
+ }
|
|
1072
|
+
|
|
1073
|
+ if config.Accounts.AuthScript.Enabled {
|
|
1074
|
+ var output AuthScriptOutput
|
|
1075
|
+ output, err = CheckAuthScript(config.Accounts.AuthScript,
|
|
1076
|
+ AuthScriptInput{AccountName: accountName, Passphrase: passphrase, IP: client.IP().String()})
|
|
1077
|
+ if err != nil {
|
|
1078
|
+ am.server.logger.Error("internal", "failed shell auth invocation", err.Error())
|
|
1079
|
+ return err
|
|
1080
|
+ }
|
|
1081
|
+ if output.Success {
|
|
1082
|
+ if output.AccountName != "" {
|
|
1083
|
+ accountName = output.AccountName
|
1063
|
1084
|
}
|
|
1085
|
+ account, err = am.loadWithAutocreation(accountName, config.Accounts.AuthScript.Autocreate)
|
1064
|
1086
|
return
|
1065
|
1087
|
}
|
1066
|
1088
|
}
|
|
@@ -1361,15 +1383,50 @@ func (am *AccountManager) ChannelsForAccount(account string) (channels []string)
|
1361
|
1383
|
return unmarshalRegisteredChannels(channelStr)
|
1362
|
1384
|
}
|
1363
|
1385
|
|
1364
|
|
-func (am *AccountManager) AuthenticateByCertFP(client *Client, certfp, authzid string) error {
|
|
1386
|
+func (am *AccountManager) AuthenticateByCertFP(client *Client, certfp, authzid string) (err error) {
|
1365
|
1387
|
if certfp == "" {
|
1366
|
1388
|
return errAccountInvalidCredentials
|
1367
|
1389
|
}
|
1368
|
1390
|
|
|
1391
|
+ var clientAccount ClientAccount
|
|
1392
|
+
|
|
1393
|
+ defer func() {
|
|
1394
|
+ if err != nil {
|
|
1395
|
+ return
|
|
1396
|
+ } else if !clientAccount.Verified {
|
|
1397
|
+ err = errAccountUnverified
|
|
1398
|
+ return
|
|
1399
|
+ }
|
|
1400
|
+ // TODO(#1109) clean this check up?
|
|
1401
|
+ if client.registered {
|
|
1402
|
+ if clientAlready := am.server.clients.Get(clientAccount.Name); clientAlready != nil && clientAlready.AlwaysOn() {
|
|
1403
|
+ err = errNickAccountMismatch
|
|
1404
|
+ return
|
|
1405
|
+ }
|
|
1406
|
+ }
|
|
1407
|
+ am.Login(client, clientAccount)
|
|
1408
|
+ return
|
|
1409
|
+ }()
|
|
1410
|
+
|
|
1411
|
+ config := am.server.Config()
|
|
1412
|
+ if config.Accounts.AuthScript.Enabled {
|
|
1413
|
+ var output AuthScriptOutput
|
|
1414
|
+ output, err = CheckAuthScript(config.Accounts.AuthScript,
|
|
1415
|
+ AuthScriptInput{Certfp: certfp, IP: client.IP().String()})
|
|
1416
|
+ if err != nil {
|
|
1417
|
+ am.server.logger.Error("internal", "failed shell auth invocation", err.Error())
|
|
1418
|
+ return err
|
|
1419
|
+ }
|
|
1420
|
+ if output.Success && output.AccountName != "" {
|
|
1421
|
+ clientAccount, err = am.loadWithAutocreation(output.AccountName, config.Accounts.AuthScript.Autocreate)
|
|
1422
|
+ return
|
|
1423
|
+ }
|
|
1424
|
+ }
|
|
1425
|
+
|
1369
|
1426
|
var account string
|
1370
|
1427
|
certFPKey := fmt.Sprintf(keyCertToAccount, certfp)
|
1371
|
1428
|
|
1372
|
|
- err := am.server.store.View(func(tx *buntdb.Tx) error {
|
|
1429
|
+ err = am.server.store.View(func(tx *buntdb.Tx) error {
|
1373
|
1430
|
account, _ = tx.Get(certFPKey)
|
1374
|
1431
|
if account == "" {
|
1375
|
1432
|
return errAccountInvalidCredentials
|
|
@@ -1386,19 +1443,8 @@ func (am *AccountManager) AuthenticateByCertFP(client *Client, certfp, authzid s
|
1386
|
1443
|
}
|
1387
|
1444
|
|
1388
|
1445
|
// ok, we found an account corresponding to their certificate
|
1389
|
|
- clientAccount, err := am.LoadAccount(account)
|
1390
|
|
- if err != nil {
|
1391
|
|
- return err
|
1392
|
|
- } else if !clientAccount.Verified {
|
1393
|
|
- return errAccountUnverified
|
1394
|
|
- }
|
1395
|
|
- if client.registered {
|
1396
|
|
- if clientAlready := am.server.clients.Get(clientAccount.Name); clientAlready != nil && clientAlready.AlwaysOn() {
|
1397
|
|
- return errNickAccountMismatch
|
1398
|
|
- }
|
1399
|
|
- }
|
1400
|
|
- am.Login(client, clientAccount)
|
1401
|
|
- return nil
|
|
1446
|
+ clientAccount, err = am.LoadAccount(account)
|
|
1447
|
+ return err
|
1402
|
1448
|
}
|
1403
|
1449
|
|
1404
|
1450
|
type settingsMunger func(input AccountSettings) (output AccountSettings, err error)
|