sp_extrapwdchecks is causing corruption is syslogins but cant figure out why , below is the corruption message and store procedure.
The error is not consistent , we just drop the procedure and then everything seems to be fine .
Code looks ok not sure how it can cause corruption or under what scenhowever if some one can suggest better way to handle it as we need the historical password check feature from the proc
logs
==========================================
06:00000:00724:2015/10/28 13:07:26.31 kernel [Handler pc: 0x00000001006b97b0 s_handle+0x0 installed by the following function:-]
06:00000:00724:2015/10/28 13:07:26.31 kernel pc: 0x00000001004dcfd4 sequencer+0x234()
06:00000:00724:2015/10/28 13:07:26.32 kernel pc: 0x00000001005662a8 tdsrecv_language+0xb8()
06:00000:00724:2015/10/28 13:07:26.32 kernel [Handler pc: 0x00000001006ae9bc ut_handle+0x0 installed by the following function:-]
06:00000:00724:2015/10/28 13:07:26.32 kernel pc: 0x00000001004df48c conn_hdlr__fdpr_6+0x3c()
06:00000:00724:2015/10/28 13:07:26.32 kernel end of stack trace, spid 724, kpid 6422915, suid 20862
06:00000:00724:2015/10/28 13:07:26.32 server Error: 644, Severity: 21, State: 5
06:00000:00724:2015/10/28 13:07:26.32 server Index row entry for data row id (409, 17) is missing from index page 1465 of index id 2 of table 'syslogins' in database 'master'. Xactid is (113623,19). Drop and re-create the index.
*** Completed showing top 100 lines from output ***
Proc sp_extrapwdchecks
==========================
use master
go
create proc sp_extrapwdchecks
(
@caller_password varchar(30), -- the current password of caller
@new_password varchar(30), -- the new password of the target acct
@loginame varchar(30) -- user to change password on
)
as
begin
declare @errno int,
@pwdlen int,
@min_length int,
@name varchar(30),
@c int,
@lastchar int,
@run int,
@msg varchar(1024),
@defdb varchar(30), /* default db for the new user */
@deflanguage varchar(30), /* default language for the new user */
@fullname varchar(30), /* account owner's full name */
@passwdexp int, /* value of password expiration */
@minpwdlen int, /* value of minimum password length */
@maxfailedlogins int /* value of maximum failed logins */
select @errno = 0
if @loginame is NULL
select @name = suser_name()
else
select @name = @loginame
declare @changing_my_own char(1)
if @loginame is NULL or @loginame = suser_name()
select @changing_my_own = "Y"
else
select @changing_my_own = "N"
declare @new_id_flag char(1)
select @new_id_flag = "N"
if not exists (select 1 from security.dbo.logins
where name = @name)
and @changing_my_own = "N"
begin
insert security..logins
select suid, /* server user id */
name, /* account name */
getdate(), /* crdate */
suser_name(), /* creator */
NULL, /* last_login */
NULL, /* lock_date */
NULL, /* unlock_date */
"N", /* pw_changed_by_user */
0, /* failed_login_count */
"N", /* lock_account flag */
0 /* lock reason */
from master.dbo.syslogins
where name = @name
select @new_id_flag = "Y" /* Bugfix 9680 */
select @defdb = dbname,
@deflanguage = language,
@fullname = fullname
from master.dbo.syslogins
where name = @name
select @passwdexp = int_value
from master.dbo.sysattributes
where class = 14
and attribute = 0
and object_type = "PS"
and object_cinfo = "login"
and object = suser_id(@name)
select @minpwdlen = int_value
from master.dbo.sysattributes
where class = 14
and attribute = 1
and object_type = "PS"
and object_cinfo = "login"
and object = suser_id(@name)
select @maxfailedlogins = int_value
from master.dbo.sysattributes
where class = 14
and attribute = 2
and object_type = "PS"
and object_cinfo = "login"
and object = suser_id(@name)
select @msg = "SMS Add Login: "
+ rtrim(@loginame)
+ ", defaultdb: "
+ rtrim(@defdb)
if @deflanguage is not null
select @msg = @msg
+ ", defaultlang: "
+ rtrim(@deflanguage)
if @fullname is not null
select @msg = @msg
+ ", full name: "
+ rtrim(@fullname)
if @passwdexp is not null
select @msg = @msg
+ ", pwd exp: "
+ rtrim(convert(varchar,@passwdexp))
if @minpwdlen is not null
select @msg = @msg
+ ", pwd len: "
+ rtrim(convert(varchar,@minpwdlen))
if @maxfailedlogins is not null
select @msg = @msg
+ ", max failed logins: "
+ rtrim(convert(varchar,@maxfailedlogins))
execute sp_addauditrecord @text = @msg
end
if @changing_my_own = "Y" and suser_name() != "sa"
and exists (select 1 from security.dbo.logins
where name = @name
and pw_changed_by_user = 'Y')
begin
if exists
(select 1
from master.dbo.syslogins
where datediff(hour,pwdate,getdate()) < 24
and name = @name)
begin
select @errno = 30001,
@msg = "You have already changed your password in the last 24 hours."
goto FAIL
end
end
/* must not have leading or trailing spaces */
if @new_password != ltrim(@new_password) or
ascii(substring(@new_password,datalength(@new_password),1)) = 32
begin
select @errno = 30002,
@msg = "Password must not have leading or trailing spaces."
goto FAIL
end
/* must not be same as name or reverse of name */
select @pwdlen = datalength(@new_password)
if @loginame is NULL
select @name = suser_name()
else
select @name = @loginame
if upper(@new_password) = upper(substring(@name,1,@pwdlen))
or upper(@new_password) = upper(substring(reverse(@name),1,@pwdlen))
begin
select @errno = 30003,
@msg = "Password cannot be same as login name."
goto FAIL
end
/* password must not be in history for this user */
if exists
(select 1
from security.dbo.password_history
where name = @name
and password = internal_encrypt(@new_password))
begin
select @errno = 30005,
@msg = "Password exists in history file"
goto FAIL
end
/* password must not be in exclusions list */
if exists
(select 1
from security.dbo.password_exclusions
where password = lower(@new_password))
begin
select @errno = 30006,
@msg = "Password disallowed."
goto FAIL
end
/* must not have any repeating char sequences > 2 */
select @c = 2,
@lastchar = ascii(substring(@new_password,1,1)),
@run = 1
while (@c <= datalength(@new_password))
begin
if ascii(substring(@new_password,@c,1)) = @lastchar
begin
select @run = @run + 1
if @run > 2
begin
select @errno = 30007,
@msg = "Password contains prohibited repeating character sequence."
goto FAIL
end
end
else
select @run = 1
select @lastchar = ascii(substring(@new_password,@c,1)),
@c = @c + 1
end
/* must not have any ascending sequences > 3 chars */
select @c = 2,
@lastchar = ascii(substring(@new_password,1,1)),
@run = 1
while (@c <= datalength(@new_password))
begin
if ascii(substring(@new_password,@c,1)) = @lastchar+1
begin
select @run = @run + 1
if @run > 3
begin
select @errno = 30007,
@msg = "Password contains prohibited ascending character sequence."
goto FAIL
end
end
else
select @run = 1
select @lastchar = ascii(substring(@new_password,@c,1)),
@c = @c + 1
end
/* must not have any descending sequences > 3 chars */
select @c = 2,
@lastchar = ascii(substring(@new_password,1,1)),
@run = 1
while (@c <= datalength(@new_password))
begin
if ascii(substring(@new_password,@c,1)) = @lastchar-1
begin
select @run = @run + 1
if @run > 3
begin
select @errno = 30008,
@msg = "Password contains prohibited descending character sequence."
goto FAIL
end
end
else
select @run = 1
select @lastchar = ascii(substring(@new_password,@c,1)),
@c = @c + 1
end
/*
** now update password_history list in security IF we have the old
** password. We don't have it if the password is being reset for the user by
** sa or sso, in which case there's a hole in the history. We can't do anything
** about this until Sybase enhance the encryption to make it available to T-SQL
*/
if @changing_my_own = "Y"
begin
/*
** make an entry in the password history table
*/
insert security.dbo.password_history
values (@name, /* name - account name being modified */
0, /* password_version - will be corrected by trigger */
isnull(internal_encrypt(@caller_password),"NULL"), /* previous password */
getdate(), /* change_date */
suser_name()) /* changed_by - who changed the password */
/*
** update security logins table to show user changed his own password
*/
update security.dbo.logins
set pw_changed_by_user = "Y"
where name = @name
end
else
begin
/*
** password is being changed for user by sa or other, so just make entry in
** in history if password is unknown.
*/
insert security.dbo.password_history
select @name, /* name - account name being modified */
0, /* password_version - will be corrected by trigger */
isnull(password, internal_encrypt("[UNKNOWN]")), /* previous password */
getdate(), /* change_date */
suser_name() /* changed_by - who changed the password */
from master.dbo.syslogins
where name = @name
/*
** update security logins table to show user had password changed for him by sso/sa
** and reset login failure indicators
*/
update security.dbo.logins
set pw_changed_by_user = "N",
failed_login_count = 0
where name = @name
/*
** if the account is locked, might as well unlock it
*/
if exists
(select 1
from master.dbo.syslogins
where name = @name
and status & 2 = 2)
begin
execute sp_locklogin @name, 'unlock'
end
end
select @errno = @@ERROR
if @errno > 0
goto FAIL
/*
** check if we need to expire the password straight away
**
** we need to expire password if this is called from sp_addlogin, or an sso
** is changing somebody's password for them. In either case @loginame is NOT NULL
** and is not equal to the current user. However, this feature does not happen
** to "sa" activity
*/
-- this update does not seem to work in sp_extrapwdchecks, logic to use pw_changed_by_user
-- from security.dbo.logins used in above 24-hour check.
--if @changing_my_own = "N"
-- update master.dbo.syslogins
-- set pwdate = "Jan 1 1990" /* should cover even the most lax regime */
-- where name = @loginame
if @changing_my_own = "N" /* only audit sso changing other people's pwds */
begin
select @msg = "SMS Password Change: " + rtrim(@loginame)
execute sp_addauditrecord @text = @msg
end
return (0)
/*
** The raiserror must be at end of the procedure, else it does not seem to return a non-zero value to the
** set_password function in sp_password.
** Do NOT add a "return (@errno)" after raiserror.
** Conjecture: In 12.5.4, set_password calls sp_extrapwdchecks and then looks for @@error from raiserror.
** A return statement after raiserror, resets @@error to 0, so set_password thinks it's okay (???).
*/
FAIL:
if @errno != 0 and @errno != 30021 /* 30021 = warning from password_history trigger */
begin
/** Begin Modification 9680 - rollback the newly inserted ID from security.dbo.logins**/
if exists (select 1 from security.dbo.logins
where name = @name )
and @changing_my_own = "N"
and @new_id_flag = "Y"
begin
delete security.dbo.logins
where name = @name
end
/** End Modification 9680 **/
raiserror @errno @msg /* do NOT have a return after this raiserror for 12.5.4 */
end
else
begin
return (0)
end
end
go
grant execute on sp_extrapwdchecks to public
go