View RSS Feed

TheScarfedOne

Exporting SQL Logons

Rate this Entry
by , 15th August 2012 at 09:44 AM (6807 Views)
Another diversion from my usual blog posts - but this one came out of necessity, when I had issues with my SQL databases for SIMS and FMS. Many of you may know that FMS has its own "SQL" logins, as does SIMS - but at least with that, you can set it to use Windows Authentication.

Anyway, my problem - I was greeted by FMS with the lovely "Cannot rollback atomic" error whenever logging in. It turns out this error (after some digging) has lots of causes - none of them really to do with SIMS or FMS.

This error is documented here FMS Fault most recently, and FMS problem historically. There are also some SupportNet articles on it too.

It is, as the error states an SQL error. Essentially - what has happened is that a transaction is in a "stuck state" relating to a login. Ways of clearing it... well first off - when was your last backup - and have you been doing backups using DBAttach.

If not, then we are going to need a copy of all the SQL logins so we can recreate them. If you detattach and reattach a SIMS/FMS DB without it (ie move a server) - then you wont have you logins brought across.

The script to do this is as shown below. You need SQL Management Studio for this, and then you are thinking - how do I run it? Well, copy and paste it into a "New Query" (yes - click the "New Query" button in Studio. Then, its Execute. The output from this needs saving somewhere safe.

Next up, run DBAttach to dettach the database. This will run its own backup - but I would still take your own first. Then - go into your SQL Data folder, and copy (yes, copy) the two database files for FMS (and or SIMS) out somewhere else for safe keeping. Rename them something sensible (like add the date and time on the end). Remove them from the SQL Data folder... as when you run DBAttach to re-attach the DBS (point at your backup, or the files you just had) - it will copy them back into the SQL Data folder.

Check after doing the DBAttach (to dettach...confused with all that yet!) that the DB has gone from SQL Studio. Also look in the Logins under Security whether your user accounts are still there. If the first time of this full procedure fails, I would try removing your offending logins - as the import script (the output of running the query script shown here) will recreate them.

Hope this helps.

Of course - this is all at your own risk, and will not be supported by Capita. That being said, this is likely what they do if they have to have your DB to look at - and its what I did with my local support team.

Code:
USE master
GO
IF OBJECT_ID ('sp_hexadecimal') IS NOT NULL
  DROP PROCEDURE sp_hexadecimal
GO
CREATE PROCEDURE sp_hexadecimal
    @binvalue varbinary(256),
    @Hexvalue varchar (514) OUTPUT
AS
DECLARE @charvalue varchar (514)
DECLARE @i int
DECLARE @length int
DECLARE @Hexstring char(16)
SELECT @charvalue = '0x'
SELECT @i = 1
SELECT @length = DATALENGTH (@binvalue)
SELECT @Hexstring = '0123456789ABCDEF'
WHILE (@i <= @length)
BEGIN
  DECLARE @tempint int
  DECLARE @firstint int
  DECLARE @secondint int
  SELECT @tempint = CONVERT(int, SUBSTRING(@binvalue,@i,1))
  SELECT @firstint = FLOOR @tempint/16)
  SELECT @secondint = @tempint - (@firstint*16)
  SELECT @charvalue = @charvalue +
    SUBSTRING @Hexstring, @firstint+1, 1) +
    SUBSTRING @Hexstring, @secondint+1, 1)
  SELECT @i = @i + 1
END

SELECT @Hexvalue = @charvalue
GO
 
IF OBJECT_ID ('sp_help_revlogin') IS NOT NULL
  DROP PROCEDURE sp_help_revlogin
GO
CREATE PROCEDURE sp_help_revlogin @login_name sysname = NULL AS
DECLARE @name sysname
DECLARE @type varchar (1)
DECLARE @hasaccess int
DECLARE @denylogin int
DECLARE @is_disabled int
DECLARE @PWD_varbinary  varbinary (256)
DECLARE @PWD_string  varchar (514)
DECLARE @sid_varbinary varbinary (85)
DECLARE @sid_string varchar (514)
DECLARE @tmpstr  varchar (1024)
DECLARE @is_policy_checked varchar (3)
DECLARE @is_expiration_checked varchar (3)

DECLARE @defaultdb sysname
 
IF  @login_name IS NULL)
  DECLARE login_curs CURSOR FOR

      SELECT p.sid, p.name, p.type, p.is_disabled, p.default_database_name, l.hasaccess, l.denylogin FROM 
sys.server_principals p LEFT JOIN sys.syslogins l
      ON ( l.name = p.name ) WHERE p.type IN ( 'S', 'G', 'U' ) AND p.name <> 'sa'
ELSE
  DECLARE login_curs CURSOR FOR


      SELECT p.sid, p.name, p.type, p.is_disabled, p.default_database_name, l.hasaccess, l.denylogin FROM 
sys.server_principals p LEFT JOIN sys.syslogins l
      ON ( l.name = p.name ) WHERE p.type IN ( 'S', 'G', 'U' ) AND p.name = @login_name
OPEN login_curs

FETCH NEXT FROM login_curs INTO @sid_varbinary, @name, @type, @is_disabled, @defaultdb, @hasaccess, @denylogin
IF (@@fetch_status = -1)
BEGIN
  PRINT 'No login(s) found.'
  CLOSE login_curs
  DEALLOCATE login_curs
  RETURN -1
END
SET @tmpstr = '/* sp_help_revlogin script '
PRINT @tmpstr
SET @tmpstr = '** Generated ' + CONVERT (varchar, GETDATE()) + ' on ' + @@SERVERNAME + ' */'
PRINT @tmpstr
PRINT ''
WHILE (@@fetch_status <> -1)
BEGIN
  IF (@@fetch_status <> -2)
  BEGIN
    PRINT ''
    SET @tmpstr = '-- Login: ' + @name
    PRINT @tmpstr
    IF (@type IN ( 'G', 'U'))
    BEGIN -- NT authenticated account/group

      SET @tmpstr = 'CREATE LOGIN ' + QUOTENAME( @name ) + ' FROM WINDOWS WITH DEFAULT_DATABASE = [' + @defaultdb + ']'
    END
    ELSE BEGIN -- SQL Server authentication
        -- obtain password and sid
            SET @PWD_varbinary = CAST( LOGINPROPERTY( @name, 'PasswordHash' ) AS varbinary (256) )
        EXEC sp_hexadecimal @PWD_varbinary, @PWD_string OUT
        EXEC sp_hexadecimal @sid_varbinary @sid_string OUT
 
        -- obtain password policy state
        SELECT @is_policy_checked = CASE is_policy_checked WHEN 1 THEN 'ON' WHEN 0 THEN 'OFF' ELSE NULL END FROM sys.sql_logins WHERE name = @name
        SELECT @is_expiration_checked = CASE is_expiration_checked WHEN 1 THEN 'ON' WHEN 0 THEN 'OFF' ELSE NULL END FROM sys.sql_logins WHERE name = @name
 
            SET @tmpstr = 'CREATE LOGIN ' + QUOTENAME( @name ) + ' WITH PASSWORD = ' + @PWD_string + ' HASHED, SID = ' + @sid_string + ', DEFAULT_DATABASE = [' + @defaultdb + ']'

        IF ( @is_policy_checked IS NOT NULL )
        BEGIN
          SET @tmpstr = @tmpstr + ', CHECK_POLICY = ' + @is_policy_checked
        END
        IF ( @is_expiration_checked IS NOT NULL )
        BEGIN
          SET @tmpstr = @tmpstr + ', CHECK_EXPIRATION = ' + @is_expiration_checked
        END
    END
    IF  @denylogin = 1)
    BEGIN -- login is denied access
      SET @tmpstr = @tmpstr + '; DENY CONNECT SQL TO ' + QUOTENAME( @name )
    END
    ELSE IF  @hasaccess = 0)
    BEGIN -- login exists but does not have access
      SET @tmpstr = @tmpstr + '; REVOKE CONNECT SQL TO ' + QUOTENAME( @name )
    END
    IF (@is_disabled = 1)
    BEGIN -- login is disabled
      SET @tmpstr = @tmpstr + '; ALTER LOGIN ' + QUOTENAME( @name ) + ' DISABLE'
    END
    PRINT @tmpstr
  END

  FETCH NEXT FROM login_curs INTO @sid_varbinary, @name, @type, @is_disabled, @defaultdb, @hasaccess, @denylogin
   END
CLOSE login_curs
DEALLOCATE login_curs
RETURN 0
GO
Tags: fms, sims, sql
Categories
Software

Comments

Trackbacks

Total Trackbacks 0
Trackback URL: