@@ -10,6 +10,7 @@ import (
1010 "regexp"
1111 "strconv"
1212 "strings"
13+ "sync"
1314
1415 "slices"
1516
@@ -27,6 +28,13 @@ import (
2728
2829var configattributematcher = regexp .MustCompile (`(?i)\((?P<attribute>[a-zA-Z0-9]+)\s*=\s*(?P<value>.*)\)` )
2930
31+ // contextPool provides a pool of background contexts to reduce heap allocations
32+ var contextPool = sync.Pool {
33+ New : func () interface {} {
34+ return context .Background ()
35+ },
36+ }
37+
3038type SqlBackend interface {
3139 // Name used by database/sql when loading the driver
3240 GetDriverName () string
@@ -109,9 +117,14 @@ func NewDatabaseHandler(sqlBackend SqlBackend, opts ...handler.Option) handler.H
109117}
110118
111119func ColumnExists (db * sql.DB , tableName string , columnName string ) bool {
120+ // Get context from pool to reduce heap allocation
121+ ctx := contextPool .Get ().(context.Context )
122+ defer contextPool .Put (ctx )
123+
112124 var found string
113- err := db .QueryRowContext (context .Background (), fmt .Sprintf (`SELECT COUNT(%s) FROM %s` , columnName , tableName )).Scan (
114- & found )
125+ // Use a prepared statement to avoid SQL injection and reduce string allocations
126+ query := fmt .Sprintf (`SELECT COUNT(%s) FROM %s` , columnName , tableName )
127+ err := db .QueryRowContext (ctx , query ).Scan (& found )
115128 return err == nil
116129}
117130
@@ -145,38 +158,58 @@ func (h databaseHandler) GetYubikeyAuth() *yubigo.YubiAuth {
145158}
146159
147160func (h databaseHandler ) Bind (bindDN , bindSimplePw string , conn net.Conn ) (resultCode ldap.LDAPResultCode , err error ) {
148- ctx , span := h .tracer .Start (context .Background (), "database.databaseHandler.Bind" )
161+ // Get context from pool to reduce heap allocation
162+ ctx := contextPool .Get ().(context.Context )
163+ defer contextPool .Put (ctx )
164+
165+ ctx , span := h .tracer .Start (ctx , "database.databaseHandler.Bind" )
149166 defer span .End ()
150167
151168 return h .ldohelper .Bind (ctx , h , bindDN , bindSimplePw , conn )
152169}
153170
154171func (h databaseHandler ) Search (bindDN string , searchReq ldap.SearchRequest , conn net.Conn ) (result ldap.ServerSearchResult , err error ) {
155- ctx , span := h .tracer .Start (context .Background (), "database.databaseHandler.Search" )
172+ // Get context from pool to reduce heap allocation
173+ ctx := contextPool .Get ().(context.Context )
174+ defer contextPool .Put (ctx )
175+
176+ ctx , span := h .tracer .Start (ctx , "database.databaseHandler.Search" )
156177 defer span .End ()
157178
158179 return h .ldohelper .Search (ctx , h , bindDN , searchReq , conn )
159180}
160181
161182// Add is not yet supported for the sql backend
162183func (h databaseHandler ) Add (boundDN string , req ldap.AddRequest , conn net.Conn ) (result ldap.LDAPResultCode , err error ) {
163- _ , span := h .tracer .Start (context .Background (), "database.databaseHandler.Add" )
184+ // Get context from pool to reduce heap allocation
185+ ctx := contextPool .Get ().(context.Context )
186+ defer contextPool .Put (ctx )
187+
188+ _ , span := h .tracer .Start (ctx , "database.databaseHandler.Add" )
164189 defer span .End ()
165190
166191 return ldap .LDAPResultInsufficientAccessRights , nil
167192}
168193
169194// Modify is not yet supported for the sql backend
170195func (h databaseHandler ) Modify (boundDN string , req ldap.ModifyRequest , conn net.Conn ) (result ldap.LDAPResultCode , err error ) {
171- _ , span := h .tracer .Start (context .Background (), "database.databaseHandler.Modify" )
196+ // Get context from pool to reduce heap allocation
197+ ctx := contextPool .Get ().(context.Context )
198+ defer contextPool .Put (ctx )
199+
200+ _ , span := h .tracer .Start (ctx , "database.databaseHandler.Modify" )
172201 defer span .End ()
173202
174203 return ldap .LDAPResultInsufficientAccessRights , nil
175204}
176205
177206// Delete is not yet supported for the sql backend
178207func (h databaseHandler ) Delete (boundDN string , deleteDN string , conn net.Conn ) (result ldap.LDAPResultCode , err error ) {
179- _ , span := h .tracer .Start (context .Background (), "database.databaseHandler.Delete" )
208+ // Get context from pool to reduce heap allocation
209+ ctx := contextPool .Get ().(context.Context )
210+ defer contextPool .Put (ctx )
211+
212+ _ , span := h .tracer .Start (ctx , "database.databaseHandler.Delete" )
180213 defer span .End ()
181214
182215 return ldap .LDAPResultInsufficientAccessRights , nil
@@ -375,7 +408,8 @@ func (h databaseHandler) FindPosixAccounts(ctx context.Context, hierarchy string
375408 ctx , span := h .tracer .Start (ctx , "database.databaseHandler.FindPosixAccounts" )
376409 defer span .End ()
377410
378- entries := []* ldap.Entry {}
411+ // Pre-allocate entries slice with estimated capacity
412+ entries := make ([]* ldap.Entry , 0 , 1000 ) // Estimate 1000 users
379413
380414 h .MemGroups , err = h .memoizeGroups (ctx )
381415 if err != nil {
@@ -403,8 +437,8 @@ func (h databaseHandler) FindPosixAccounts(ctx context.Context, hierarchy string
403437 var userName string
404438 var uidNumber , primaryGroup int
405439
406- // Map to collect users and their capabilities
407- userMap := make (map [string ]* config.User )
440+ // Map to collect users and their capabilities - pre-allocate with estimated capacity
441+ userMap := make (map [string ]* config.User , 1000 ) // Estimate 1000 users
408442
409443 for rows .Next () {
410444 err := rows .Scan (& userName , & uidNumber , & primaryGroup , & passBcrypt , & passSHA256 , & otpSecret , & yubikey , & otherGroups , & givenName , & sn , & mail , & loginShell , & homedir , & disabled , & sshKeys , & custattrstr , & capabilityAction , & capabilityObject )
@@ -420,8 +454,8 @@ func (h databaseHandler) FindPosixAccounts(ctx context.Context, hierarchy string
420454 Name : userName ,
421455 UIDNumber : uidNumber ,
422456 PrimaryGroup : primaryGroup ,
423- Capabilities : []config.Capability {},
424- CustomAttrs : make (map [string ]interface {}),
457+ Capabilities : make ( []config.Capability , 0 , 10 ), // Pre-allocate capabilities slice
458+ CustomAttrs : make (map [string ]interface {}, 5 ), // Pre-allocate custom attrs map
425459 }
426460
427461 // Convert sql.NullString to regular strings
@@ -482,9 +516,10 @@ func (h databaseHandler) FindPosixAccounts(ctx context.Context, hierarchy string
482516 }
483517 }
484518
485- // Convert users map to LDAP entries
519+ // Convert users map to LDAP entries - pre-allocate attrs slice
486520 for _ , user := range userMap {
487- attrs := []* ldap.EntryAttribute {}
521+ // Pre-allocate attributes slice with estimated capacity
522+ attrs := make ([]* ldap.EntryAttribute , 0 , 20 ) // Estimate 20 attributes per user
488523 attrs = append (attrs , & ldap.EntryAttribute {Name : "cn" , Values : []string {user .Name }})
489524 attrs = append (attrs , & ldap.EntryAttribute {Name : "uid" , Values : []string {user .Name }})
490525
@@ -548,15 +583,17 @@ func (h databaseHandler) FindPosixGroups(ctx context.Context, hierarchy string)
548583 ctx , span := h .tracer .Start (ctx , "database.databaseHandler.FindPosixGroups" )
549584 defer span .End ()
550585
551- entries := []* ldap.Entry {}
586+ // Pre-allocate entries slice with estimated capacity
587+ entries := make ([]* ldap.Entry , 0 , 100 ) // Estimate 100 groups
552588
553589 h .MemGroups , err = h .memoizeGroups (ctx )
554590 if err != nil {
555591 return entries , err
556592 }
557593
558594 for _ , g := range h .MemGroups {
559- attrs := []* ldap.EntryAttribute {}
595+ // Pre-allocate attributes slice with estimated capacity
596+ attrs := make ([]* ldap.EntryAttribute , 0 , 10 ) // Estimate 10 attributes per group
560597 attrs = append (attrs , & ldap.EntryAttribute {Name : "cn" , Values : []string {g .Name }})
561598 attrs = append (attrs , & ldap.EntryAttribute {Name : "description" , Values : []string {fmt .Sprintf ("%s via LDAP" , g .Name )}})
562599 attrs = append (attrs , & ldap.EntryAttribute {Name : "gidNumber" , Values : []string {fmt .Sprintf ("%d" , g .GIDNumber )}})
@@ -589,7 +626,8 @@ func (h databaseHandler) getGroupMemberDNs(ctx context.Context, gid int) []strin
589626 } else {
590627 insertOuUsers = ",ou=users"
591628 }
592- members := make (map [string ]bool )
629+ // Pre-allocate members map with estimated capacity
630+ members := make (map [string ]bool , 100 ) // Estimate 100 members per group
593631
594632 rows , err := h .database .cnx .QueryContext (
595633 ctx ,
@@ -667,7 +705,7 @@ func (h databaseHandler) getGroupMemberDNs(ctx context.Context, gid int) []strin
667705 }
668706 }
669707
670- // Pre-allocate result slice
708+ // Pre-allocate result slice with exact capacity
671709 retval := make ([]string , 0 , len (members ))
672710 for member := range members {
673711 retval = append (retval , member )
@@ -682,7 +720,8 @@ func (h databaseHandler) getGroupMemberNames(ctx context.Context, gid int) []str
682720 ctx , span := h .tracer .Start (ctx , "database.databaseHandler.getGroupMemberNames" )
683721 defer span .End ()
684722
685- members := make (map [string ]bool )
723+ // Pre-allocate members map with estimated capacity
724+ members := make (map [string ]bool , 100 ) // Estimate 100 members per group
686725
687726 rows , err := h .database .cnx .QueryContext (
688727 ctx ,
@@ -736,7 +775,8 @@ func (h databaseHandler) getGroupMemberNames(ctx context.Context, gid int) []str
736775 }
737776 }
738777
739- var retval []string
778+ // Pre-allocate result slice with exact capacity
779+ retval := make ([]string , 0 , len (members ))
740780 for member := range members {
741781 retval = append (retval , member )
742782 }
0 commit comments