diff --git a/cmd/ftp-server-driver.go b/cmd/ftp-server-driver.go index 1733cad60..01f20fce4 100644 --- a/cmd/ftp-server-driver.go +++ b/cmd/ftp-server-driver.go @@ -253,11 +253,7 @@ func (driver *ftpDriver) CheckPasswd(c *ftp.Context, username, password string) return false, err } ldapPolicies, _ := globalIAMSys.PolicyDBGet(ldapUserDN, false, groupDistNames...) - if len(ldapPolicies) == 0 { - // no policy associated reject it. - return false, nil - } - return true, nil + return len(ldapPolicies) > 0, nil } ui, ok := globalIAMSys.GetUser(context.Background(), username) @@ -362,12 +358,20 @@ func (driver *ftpDriver) DeleteDir(ctx *ftp.Context, path string) (err error) { cctx, cancel := context.WithCancel(context.Background()) defer cancel() + if prefix == "" { + // if all objects are not deleted yet this call may fail. + return clnt.RemoveBucket(cctx, bucket) + } + objectsCh := make(chan minio.ObjectInfo) // Send object names that are needed to be removed to objectsCh go func() { defer close(objectsCh) - opts := minio.ListObjectsOptions{Prefix: prefix, Recursive: true} + opts := minio.ListObjectsOptions{ + Prefix: prefix, + Recursive: true, + } for object := range clnt.ListObjects(cctx, bucket, opts) { if object.Err != nil { return @@ -427,6 +431,10 @@ func (driver *ftpDriver) MakeDir(ctx *ftp.Context, path string) (err error) { return err } + if prefix == "" { + return clnt.MakeBucket(context.Background(), bucket, minio.MakeBucketOptions{Region: globalSite.Region}) + } + dirPath := buildMinioDir(prefix) _, err = clnt.PutObject(context.Background(), bucket, dirPath, bytes.NewReader([]byte("")), 0, diff --git a/cmd/ftp-server.go b/cmd/ftp-server.go index 371a62e21..9605184e9 100644 --- a/cmd/ftp-server.go +++ b/cmd/ftp-server.go @@ -129,10 +129,29 @@ func startSFTPServer(c *cli.Context) { // certificate details and handles authentication of ServerConns. config := &ssh.ServerConfig{ PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) { + if globalIAMSys.LDAPConfig.Enabled() { + targetUser, targetGroups, err := globalIAMSys.LDAPConfig.Bind(c.User(), string(pass)) + if err != nil { + return nil, err + } + ldapPolicies, _ := globalIAMSys.PolicyDBGet(targetUser, false, targetGroups...) + if len(ldapPolicies) == 0 { + return nil, errAuthentication + } + return &ssh.Permissions{ + CriticalOptions: map[string]string{ + ldapUser: targetUser, + ldapUserN: c.User(), + }, + Extensions: make(map[string]string), + }, nil + } + ui, ok := globalIAMSys.GetUser(context.Background(), c.User()) if !ok { return nil, errNoSuchUser } + if subtle.ConstantTimeCompare([]byte(ui.Credentials.SecretKey), pass) == 1 { return &ssh.Permissions{ CriticalOptions: map[string]string{ diff --git a/cmd/sftp-server-driver.go b/cmd/sftp-server-driver.go index 2d15763b8..6d28e9fe8 100644 --- a/cmd/sftp-server-driver.go +++ b/cmd/sftp-server-driver.go @@ -97,18 +97,15 @@ func (f *sftpDriver) getMinIOClient() (*minio.Client, error) { if err != nil { return nil, err } - ldapPolicies, _ := globalIAMSys.PolicyDBGet(targetUser, false, targetGroups...) - if len(ldapPolicies) == 0 { - return nil, errAuthentication - } expiryDur, err := globalIAMSys.LDAPConfig.GetExpiryDuration("") if err != nil { return nil, err } claims := make(map[string]interface{}) claims[expClaim] = UTCNow().Add(expiryDur).Unix() - claims[ldapUser] = targetUser - claims[ldapUserN] = f.AccessKey() + for k, v := range f.permissions.CriticalOptions { + claims[k] = v + } cred, err := auth.GetNewCredentialsWithMetadata(claims, globalActiveCred.SecretKey) if err != nil { @@ -165,6 +162,9 @@ func (f *sftpDriver) getMinIOClient() (*minio.Client, error) { } func (f *sftpDriver) AccessKey() string { + if _, ok := f.permissions.CriticalOptions["accessKey"]; !ok { + return f.permissions.CriticalOptions[ldapUserN] + } return f.permissions.CriticalOptions["accessKey"] } @@ -270,12 +270,20 @@ func (f *sftpDriver) Filecmd(r *sftp.Request) (err error) { cctx, cancel := context.WithCancel(context.Background()) defer cancel() + if prefix == "" { + // if all objects are not deleted yet this call may fail. + return clnt.RemoveBucket(cctx, bucket) + } + objectsCh := make(chan minio.ObjectInfo) // Send object names that are needed to be removed to objectsCh go func() { defer close(objectsCh) - opts := minio.ListObjectsOptions{Prefix: prefix, Recursive: true} + opts := minio.ListObjectsOptions{ + Prefix: prefix, + Recursive: true, + } for object := range clnt.ListObjects(cctx, bucket, opts) { if object.Err != nil { return @@ -305,6 +313,10 @@ func (f *sftpDriver) Filecmd(r *sftp.Request) (err error) { return errors.New("bucket name cannot be empty") } + if prefix == "" { + return clnt.MakeBucket(context.Background(), bucket, minio.MakeBucketOptions{Region: globalSite.Region}) + } + dirPath := buildMinioDir(prefix) _, err = clnt.PutObject(context.Background(), bucket, dirPath, bytes.NewReader([]byte("")), 0,