@@ -150,34 +150,60 @@ func NewClient(host, user, pass string, log logr.Logger, opts ...Option) *Client
150150 }
151151}
152152
153- // Open a connection to a Supermicro BMC using the vendor API.
154- func (c * Client ) Open (ctx context.Context ) (err error ) {
153+ func (c * Client ) login (ctx context.Context , encodeCreds bool ) error {
154+ var user , pass string
155+ if encodeCreds {
156+ user = base64 .StdEncoding .EncodeToString ([]byte (c .serviceClient .user ))
157+ pass = base64 .StdEncoding .EncodeToString ([]byte (c .serviceClient .pass ))
158+ } else {
159+ user = c .serviceClient .user
160+ pass = c .serviceClient .pass
161+ }
162+
155163 data := fmt .Sprintf (
156164 "name=%s&pwd=%s&check=00" ,
157- base64 . StdEncoding . EncodeToString ([] byte ( c . serviceClient . user )) ,
158- base64 . StdEncoding . EncodeToString ([] byte ( c . serviceClient . pass )) ,
165+ user ,
166+ pass ,
159167 )
160168
161169 headers := map [string ]string {"Content-Type" : "application/x-www-form-urlencoded" }
162170
163171 body , status , err := c .serviceClient .query (ctx , "cgi/login.cgi" , http .MethodPost , bytes .NewBufferString (data ), headers , 0 )
164172 if err != nil {
165- return errors . Wrap ( bmclibErrs . ErrLoginFailed , err . Error ())
173+ return err
166174 }
167175
168176 if status != 200 {
169- return errors .Wrap (bmclibErrs .ErrLoginFailed , strconv .Itoa (status ))
177+ return errors .Wrap (ErrUnexpectedStatusCode , strconv .Itoa (status ))
178+ }
179+
180+ // Older Supermicro boards return 200 for failed logins
181+ if ! bytes .Contains (body , []byte (`url_redirect.cgi?url_name=mainmenu` )) &&
182+ ! bytes .Contains (body , []byte (`url_redirect.cgi?url_name=topmenu` )) {
183+ return ErrUnexpectedResponse
170184 }
171185
186+ return nil
187+ }
188+
189+ // Open a connection to a Supermicro BMC using the vendor API.
190+ func (c * Client ) Open (ctx context.Context ) (err error ) {
172191 // called after a session was opened but further login dependencies failed
173192 closeWithError := func (ctx context.Context , err error ) error {
174193 _ = c .Close (ctx )
175194 return err
176195 }
177196
178- if ! bytes .Contains (body , []byte (`url_redirect.cgi?url_name=mainmenu` )) &&
179- ! bytes .Contains (body , []byte (`url_redirect.cgi?url_name=topmenu` )) {
180- return closeWithError (ctx , errors .Wrap (bmclibErrs .ErrLoginFailed , "unexpected response contents" ))
197+ // first attempt login with base64 encoded user,pass
198+ if err := c .login (ctx , true ); err != nil {
199+ if ! errors .Is (err , ErrUnexpectedResponse ) && ! errors .Is (err , ErrUnexpectedStatusCode ) {
200+ return closeWithError (ctx , errors .Wrap (bmclibErrs .ErrLoginFailed , err .Error ()))
201+ }
202+
203+ // retry with plain text user, pass
204+ if err2 := c .login (ctx , false ); err2 != nil {
205+ return closeWithError (ctx , errors .Wrap (bmclibErrs .ErrLoginFailed , err2 .Error ()))
206+ }
181207 }
182208
183209 contentsTopMenu , status , err := c .serviceClient .query (ctx , "cgi/url_redirect.cgi?url_name=topmenu" , http .MethodGet , nil , nil , 0 )
0 commit comments