From 3ae63d113f16966f8f794666a16a741e7af42844 Mon Sep 17 00:00:00 2001 From: Ansgar Becker Date: Wed, 28 Aug 2024 10:45:33 +0200 Subject: [PATCH] Issue #2014: user manager: parse SSL settings from SHOW CREATE USER, but also keep parsing SHOW GRANTS for backward compatibility --- source/usermanager.pas | 110 ++++++++++++++++++++++++++++------------- 1 file changed, 76 insertions(+), 34 deletions(-) diff --git a/source/usermanager.pas b/source/usermanager.pas index 3672ed1a..bbabe950 100644 --- a/source/usermanager.pas +++ b/source/usermanager.pas @@ -19,7 +19,9 @@ type Username, Host, Password, Cipher, Issuer, Subject: String; MaxQueries, MaxUpdates, MaxConnections, MaxUserConnections, SSL: Integer; Problem: TUserProblem; - function HostRequiresNameResolve: Boolean; + public + constructor Create; + function HostRequiresNameResolve: Boolean; end; PUser = ^TUser; TUserList = TObjectList; @@ -165,6 +167,7 @@ type procedure SetModified(Value: Boolean); property Modified: Boolean read FModified write SetModified; function GetPrivByNode(Node: PVirtualNode): TPrivObj; + procedure ParseSSLSettings(GrantOrCreate: String; User: TUser); public { Public declarations } end; @@ -502,7 +505,7 @@ procedure TUserManagerForm.listUsersFocusChanged(Sender: TBaseVirtualTree; Node: var P, Ptmp, PCol: TPrivObj; User: PUser; - UserHost, RequireClause, WithClause, Msg: String; + UserHost, WithClause, Msg, CreateUser: String; Grants, AllPNames, Cols: TStringList; rxTemp, rxGrant: TRegExpr; i, j: Integer; @@ -552,7 +555,7 @@ begin Grants.Add('GRANT USAGE ON *.* TO '+UserHost); end; end else try - Grants := FConnection.GetCol('SHOW GRANTS FOR '+FConnection.EscapeString(User.Username)+'@'+FConnection.EscapeString(User.Host)); + Grants := FConnection.GetCol('SHOW GRANTS FOR '+UserHost); except on E:EDbError do begin Msg := E.Message; @@ -677,37 +680,7 @@ begin end; - // REQUIRE SSL X509 ISSUER '456' SUBJECT '789' CIPHER '123' NONE - rxTemp.Expression := '\sREQUIRE\s+(.+)'; - if rxTemp.Exec(rxGrant.Match[11]) then begin - RequireClause := rxTemp.Match[1]; - User.SSL := 0; - User.Cipher := ''; - User.Issuer := ''; - User.Subject := ''; - rxTemp.Expression := '\bSSL\b'; - if rxTemp.Exec(RequireClause) then - User.SSL := 1; - rxTemp.Expression := '\bX509\b'; - if rxTemp.Exec(RequireClause) then - User.SSL := 2; - rxTemp.Expression := '\bCIPHER\s+''([^'']+)'; - if rxTemp.Exec(RequireClause) then - User.Cipher := rxTemp.Match[1]; - rxTemp.Expression := '\bISSUER\s+''([^'']+)'; - if rxTemp.Exec(RequireClause) then - User.Issuer := rxTemp.Match[1]; - rxTemp.Expression := '\bSUBJECT\s+''([^'']+)'; - if rxTemp.Exec(RequireClause) then - User.Subject := rxTemp.Match[1]; - if IsNotEmpty(User.Cipher) or IsNotEmpty(User.Issuer) or IsNotEmpty(User.Subject) then - User.SSL := 3; - comboSSL.ItemIndex := User.SSL; - comboSSL.OnChange(Sender); - editCipher.Text := User.Cipher; - editIssuer.Text := User.Issuer; - editSubject.Text := User.Subject; - end; + ParseSSLSettings(rxGrant.Match[11], User^); // WITH .. GRANT OPTION // MAX_QUERIES_PER_HOUR 20 MAX_UPDATES_PER_HOUR 10 MAX_CONNECTIONS_PER_HOUR 5 MAX_USER_CONNECTIONS 2 @@ -739,6 +712,16 @@ begin end; end; + + CreateUser := ''; + try + CreateUser := FConnection.GetVar('SHOW CREATE USER '+UserHost); + ParseSSLSettings(CreateUser, User^); + except + on E:EDbError do; + end; + + // Generate grant code for column privs by hand for Ptmp in FPrivObjects do begin if Ptmp.DBObj.NodeType = lntColumn then begin @@ -805,6 +788,47 @@ begin end; +procedure TUserManagerForm.ParseSSLSettings(GrantOrCreate: String; User: TUser); +var + rx: TRegExpr; + RequireClause: String; +begin + // REQUIRE SSL X509 ISSUER '456' SUBJECT '789' CIPHER '123' NONE + rx := TRegExpr.Create; + rx.ModifierI := True; + rx.Expression := '\sREQUIRE\s+(.+)'; + if rx.Exec(GrantOrCreate) then begin + RequireClause := rx.Match[1]; + User.SSL := 0; + User.Cipher := ''; + User.Issuer := ''; + User.Subject := ''; + rx.Expression := '\bSSL\b'; + if rx.Exec(RequireClause) then + User.SSL := 1; + rx.Expression := '\bX509\b'; + if rx.Exec(RequireClause) then + User.SSL := 2; + rx.Expression := '\bCIPHER\s+''([^'']+)'; + if rx.Exec(RequireClause) then + User.Cipher := rx.Match[1]; + rx.Expression := '\bISSUER\s+''([^'']+)'; + if rx.Exec(RequireClause) then + User.Issuer := rx.Match[1]; + rx.Expression := '\bSUBJECT\s+''([^'']+)'; + if rx.Exec(RequireClause) then + User.Subject := rx.Match[1]; + if IsNotEmpty(User.Cipher) or IsNotEmpty(User.Issuer) or IsNotEmpty(User.Subject) then + User.SSL := 3; + + comboSSL.ItemIndex := User.SSL; + comboSSL.OnChange(comboSSL); + editCipher.Text := User.Cipher; + editIssuer.Text := User.Issuer; + editSubject.Text := User.Subject; + end; +end; + procedure TUserManagerForm.listUsersGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: TImageIndex); var @@ -1518,6 +1542,24 @@ begin end; +{ TUser } + +constructor TUser.Create; +begin + Username := ''; + Host := ''; + Password := ''; + Cipher := ''; + Issuer := ''; + Subject := ''; + MaxQueries := 0; + MaxUpdates := 0; + MaxConnections := 0; + MaxUserConnections := 0; + SSL := 0; + Problem := upNone; +end; + function TUser.HostRequiresNameResolve: Boolean; var rx: TRegExpr;