XBee Transmit Request broadcast - xbee

I'm trying to send a broadcast using a router on a XBee S2 network.
All the devices are properly configured and have joined the network, but the packet is not being received.
I'm sending
7E 00 11 10 01 00 00 00 00 00 00 FF FF 00 00 00 00 41 42 43 2A
to the module.
What am I doing wrong?

You are not setting the 16-bit network address to 0xFFFE.
You have to send
7E 00 11 10 01 00 00 00 00 00 00 FF FF FF FE 00 00 41 42 43 2D

Related

Why does JDBC return no results from a stored procedure?

I call a stored procedure using JDBC:
Connection con = DriverManager.getConnection("jdbc:sqlserver://myhost;databaseName=mydb;encrypt=false","user", "pass");
con.setAutoCommit(false);
CallableStatement cs = con.prepareCall("{call abc(?,?,?,?,?,?,?)}");
cs.setDate(1, java.sql.Date.valueOf(LocalDate.of(2023, 1, 10)));
cs.setDate(2, java.sql.Date.valueOf(LocalDate.of(2023, 1, 9)));
cs.setString(3, "PROD");
cs.registerOutParameter(4, Types.NUMERIC);
cs.registerOutParameter(5, Types.NUMERIC);
cs.registerOutParameter(6, Types.NUMERIC);
cs.registerOutParameter(7, Types.NUMERIC);
cs.executeQuery();
I get a SQLServerException:
2023-01-13T11:22:48.975-06:00 DEBUG 21888 --- [restartedMain]
c.m.s.jdbc.internals.SQLServerException : ***
SQLException:SQLServerCallableStatement:5
com.microsoft.sqlserver.jdbc.SQLServerException: The statement did not
return a result set. The statement did not return a result set.
But I get no error calling it with Hibernate:
StoredProcedureQuery query = em.createStoredProcedureQuery("abc")
.registerStoredProcedureParameter(
"date1",
LocalDate.class,
ParameterMode.IN
)
.registerStoredProcedureParameter(
"date2",
LocalDate.class,
ParameterMode.IN
)
.registerStoredProcedureParameter(
"name",
String.class,
ParameterMode.IN
)
.registerStoredProcedureParameter(
"value1",
BigDecimal.class,
ParameterMode.OUT
)
.registerStoredProcedureParameter(
"value2",
BigDecimal.class,
ParameterMode.OUT
)
.registerStoredProcedureParameter(
"value3",
BigDecimal.class,
ParameterMode.OUT
)
.registerStoredProcedureParameter(
"value4",
BigDecimal.class,
ParameterMode.OUT
)
.setParameter("date1", LocalDate.of(2023, 1, 10))
.setParameter("date2", LocalDate.of(2023, 1, 9))
.setParameter("name", "PROD");
query.execute();
log.info("value2 is {}", query.getOutputParameterValue("value2"));
What am I doing wrong with my JDBC call?
I looked at the TRACE log from the SQL Server driver. The only difference in bytes going going to SQL Server is ^ and H in the first line:
JDBC
03 01 02 26 00 5E 01 00 16 00 00 00 12 00 00 00 ...&.^..........
02 00 00 00 00 00 00 00 00 00 01 00 00 00 FF FF ................
0A 00 00 00 00 00 E7 40 1F 09 04 D0 00 34 96 00 .......#.....4..
45 00 58 00 45 00 43 00 20 00 74 00 65 00 6D 00 E.X.E.C. .a.b.c.
Hibernate
03 01 02 26 26 00 48 01 00 16 00 00 12 00 00 00 ...&.H..........
02 00 00 00 00 00 00 00 00 00 01 00 00 00 FF FF ................
0A 00 00 00 00 00 E7 40 1F 09 04 D0 00 34 96 00 .......#.....4..
45 00 58 00 45 00 43 00 20 00 74 00 65 00 6D 00 E.X.E.C. .a.b.c.
The Hibernate code calls execute() which expects no result set. However, the JDBC code is calling executeQuery() and that expects a result set. Since the stored procedure doesn't return a result set, the SQL Server exception is thrown.
I changed the JDBC code to execute(), and it works the same as the Hibernate code.

How to read binary executable by instructions?

is there a way to read given amount of instructions from a binary executable file on x86 architecture programmatically?
If I had a binary of a simple C program hello.c:
#include <stdio.h>
int main(){
printf("Hello world\n");
return 0;
}
Where after compilation using gcc, the disassembled function main looks like this:
000000000000063a <main>:
63a: 55 push %rbp
63b: 48 89 e5 mov %rsp,%rbp
63e: 48 8d 3d 9f 00 00 00 lea 0x9f(%rip),%rdi # 6e4 <_IO_stdin_used+0x4>
645: e8 c6 fe ff ff callq 510 <puts#plt>
64a: b8 00 00 00 00 mov $0x0,%eax
64f: 5d pop %rbp
650: c3 retq
651: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
658: 00 00 00
65b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
Is there an easy way in C to read for example first three instructions (meaning the bytes 55, 48, 89, e5, 48, 8d, 3d, 9f, 00, 00, 00) from main? It is not guaranteed that the function looks like this - the first instructions may have all different opcodes and sizes.
this prints the 10 first bytes of the main function by taking the address of the function and converting to a pointer of unsigned char, print in hex.
This small snippet doesn't count the instructions. For this you would need an instruction size table (not very difficult, just tedious unless you find the table already done, What is the size of each asm instruction?) to be able to predict the size of each instruction given the first byte.
(unless of course, the processor you're targetting has a fixed instruction size, which makes the problem trivial to solve)
Debuggers have to decode operands as well, but in some cases like step or trace, I suspect they have a table handy to compute the next breakpoint address.
#include <stdio.h>
int main(){
printf("Hello world\n");
const unsigned char *start = (const char *)&main;
int i;
for (i=0;i<10;i++)
{
printf("%x\n",start[i]);
}
return 0;
}
output:
Hello world
55
89
e5
83
e4
f0
83
ec
20
e8
seems to match the disassembly :)
00401630 <_main>:
401630: 55 push %ebp
401631: 89 e5 mov %esp,%ebp
401633: 83 e4 f0 and $0xfffffff0,%esp
401636: 83 ec 20 sub $0x20,%esp
401639: e8 a2 01 00 00 call 4017e0 <___main>
.globl _start
_start:
bl main
b .
.globl main
main:
add r1,#1
add r2,#1
add r3,#1
add r4,#1
b main
intentionally wrong architecture, architecture doesnt matter file format matters. built this into an elf file format, which is very popular, and is simply a file format which is what I understood your question to be, to read a file, not modify the binary to read the program runtime from memory.
it is very much popular and there are tools that do it which you appear to know how to run.
Disassembly of section .text:
00001000 <_start>:
1000: eb000000 bl 1008 <main>
1004: eafffffe b 1004 <_start+0x4>
00001008 <main>:
1008: e2811001 add r1, r1, #1
100c: e2822001 add r2, r2, #1
1010: e2833001 add r3, r3, #1
1014: e2844001 add r4, r4, #1
1018: eafffffa b 1008 <main>
if I hexdump the file though
00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 02 00 28 00 01 00 00 00 00 10 00 00 34 00 00 00 |..(.........4...|
00000020 c0 11 00 00 00 02 00 05 34 00 20 00 01 00 28 00 |........4. ...(.|
00000030 06 00 05 00 01 00 00 00 00 00 00 00 00 00 00 00 |................|
00000040 00 00 00 00 1c 10 00 00 1c 10 00 00 05 00 00 00 |................|
00000050 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00001000 00 00 00 eb fe ff ff ea 01 10 81 e2 01 20 82 e2 |............. ..|
00001010 01 30 83 e2 01 40 84 e2 fa ff ff ea 41 11 00 00 |.0...#......A...|
00001020 00 61 65 61 62 69 00 01 07 00 00 00 08 01 00 00 |.aeabi..........|
00001030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00001040 00 00 00 00 00 10 00 00 00 00 00 00 03 00 01 00 |................|
00001050 00 00 00 00 00 00 00 00 00 00 00 00 03 00 02 00 |................|
00001060 01 00 00 00 00 00 00 00 00 00 00 00 04 00 f1 ff |................|
00001070 06 00 00 00 00 10 00 00 00 00 00 00 00 00 01 00 |................|
00001080 18 00 00 00 1c 10 01 00 00 00 00 00 10 00 01 00 |................|
00001090 09 00 00 00 1c 10 01 00 00 00 00 00 10 00 01 00 |................|
000010a0 17 00 00 00 1c 10 01 00 00 00 00 00 10 00 01 00 |................|
000010b0 55 00 00 00 00 10 00 00 00 00 00 00 10 00 01 00 |U...............|
000010c0 23 00 00 00 1c 10 01 00 00 00 00 00 10 00 01 00 |#...............|
000010d0 2f 00 00 00 08 10 00 00 00 00 00 00 10 00 01 00 |/...............|
000010e0 34 00 00 00 1c 10 01 00 00 00 00 00 10 00 01 00 |4...............|
000010f0 3c 00 00 00 1c 10 01 00 00 00 00 00 10 00 01 00 |<...............|
00001100 43 00 00 00 1c 10 01 00 00 00 00 00 10 00 01 00 |C...............|
00001110 48 00 00 00 00 00 08 00 00 00 00 00 10 00 01 00 |H...............|
00001120 4f 00 00 00 1c 10 01 00 00 00 00 00 10 00 01 00 |O...............|
00001130 00 73 6f 2e 6f 00 24 61 00 5f 5f 62 73 73 5f 73 |.so.o.$a.__bss_s|
00001140 74 61 72 74 5f 5f 00 5f 5f 62 73 73 5f 65 6e 64 |tart__.__bss_end|
00001150 5f 5f 00 5f 5f 62 73 73 5f 73 74 61 72 74 00 6d |__.__bss_start.m|
00001160 61 69 6e 00 5f 5f 65 6e 64 5f 5f 00 5f 65 64 61 |ain.__end__._eda|
00001170 74 61 00 5f 65 6e 64 00 5f 73 74 61 63 6b 00 5f |ta._end._stack._|
00001180 5f 64 61 74 61 5f 73 74 61 72 74 00 00 2e 73 79 |_data_start...sy|
00001190 6d 74 61 62 00 2e 73 74 72 74 61 62 00 2e 73 68 |mtab..strtab..sh|
000011a0 73 74 72 74 61 62 00 2e 74 65 78 74 00 2e 41 52 |strtab..text..AR|
000011b0 4d 2e 61 74 74 72 69 62 75 74 65 73 00 00 00 00 |M.attributes....|
000011c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000011e0 00 00 00 00 00 00 00 00 1b 00 00 00 01 00 00 00 |................|
000011f0 06 00 00 00 00 10 00 00 00 10 00 00 1c 00 00 00 |................|
00001200 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 |................|
00001210 21 00 00 00 03 00 00 70 00 00 00 00 00 00 00 00 |!......p........|
00001220 1c 10 00 00 12 00 00 00 00 00 00 00 00 00 00 00 |................|
00001230 01 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 |................|
00001240 00 00 00 00 00 00 00 00 30 10 00 00 00 01 00 00 |........0.......|
00001250 04 00 00 00 05 00 00 00 04 00 00 00 10 00 00 00 |................|
00001260 09 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 |................|
00001270 30 11 00 00 5c 00 00 00 00 00 00 00 00 00 00 00 |0...\...........|
00001280 01 00 00 00 00 00 00 00 11 00 00 00 03 00 00 00 |................|
00001290 00 00 00 00 00 00 00 00 8c 11 00 00 31 00 00 00 |............1...|
000012a0 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
000012b0
can google the file format and find a lot of info at wikipedia, with a smidge more at one of the links
useful header information
00 10 00 00 entrh
34 00 00 00 phoff
c0 11 00 00 shoff
00 02 00 05 flags
34 00 ehsize
20 00 phentsize
01 00 phnum
28 00 shentsize
06 00 shnum
05 00shstrndx
so if I look at the beginning of the sections there are shnum number of them
0x11C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x11E8 1b 00 00 00 01 00 00 00 06 00 00 00 00 10 00 00 00 10 00 00
0x1210 21 00 00 00 03 00 00 70 00 00 00 00 00 00 00 00 1c 10 00 00
0x1238 01 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 30 10 00 00
0x1260 09 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 30 11 00 00
0x1288 11 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 8c 11 00 00
0x1260 strtab type offset 0x1130 which is broken into null terminated strings until you hit a double null
[0] 00
[1] 73 6f 2e 6f 00 so.o
[2] 24 61 00 $a
[3] 5f 5f 62 73 73 5f 73 74 61 72 74 5f 5f 00 __bss_start__
[4] 5f 5f 62 73 73 5f 65 6e 64 5f 5f 00 __bss_end__
[5] 5f 5f 62 73 73 5f 73 74 61 72 74 00 __bss_start
[6] 6d 61 69 6e 00 main
...
main is at address 0x115F in the file which is offset 0x2F in the
strtab.
0x1238 symtab starts at 0x1030, 0x10 or 16 bytes per entry
00001030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00001040 00 00 00 00 00 10 00 00 00 00 00 00 03 00 01 00 |................|
00001050 00 00 00 00 00 00 00 00 00 00 00 00 03 00 02 00 |................|
00001060 01 00 00 00 00 00 00 00 00 00 00 00 04 00 f1 ff |................|
00001070 06 00 00 00 00 10 00 00 00 00 00 00 00 00 01 00 |................|
00001080 18 00 00 00 1c 10 01 00 00 00 00 00 10 00 01 00 |................|
00001090 09 00 00 00 1c 10 01 00 00 00 00 00 10 00 01 00 |................|
000010a0 17 00 00 00 1c 10 01 00 00 00 00 00 10 00 01 00 |................|
000010b0 55 00 00 00 00 10 00 00 00 00 00 00 10 00 01 00 |U...............|
000010c0 23 00 00 00 1c 10 01 00 00 00 00 00 10 00 01 00 |#...............|
000010d0 2f 00 00 00 08 10 00 00 00 00 00 00 10 00 01 00 |/...............|
000010e0 34 00 00 00 1c 10 01 00 00 00 00 00 10 00 01 00 |4...............|
000010f0 3c 00 00 00 1c 10 01 00 00 00 00 00 10 00 01 00 |<...............|
00001100 43 00 00 00 1c 10 01 00 00 00 00 00 10 00 01 00 |C...............|
00001110 48 00 00 00 00 00 08 00 00 00 00 00 10 00 01 00 |H...............|
00001120 4f 00 00 00 1c 10 01 00 00 00 00 00 10 00 01 00 |O...............|
000010d0 2f 00 00 00 has the 0x2f offset in the symbol table
so this is main, from this entry the address 08 10 00 00 or 0x1008 in
the processors memory, unfortunately due to the values I chose it happens to also be the file offset, dont get that confused.
this section is type 00000001 PROGBITS
0x11E8 1b 00 00 00 01 00 00 00 06 00 00 00 00 10 00 00 00 10 00 00
offset 0x1000 in the file 0x1C bytes
here is the program, the machine code.
00001000 00 00 00 eb fe ff ff ea 01 10 81 e2 01 20 82 e2
00001010 01 30 83 e2 01 40 84 e2 fa ff ff ea 41 11
so starting at memory offset 0x1008 which is 8 bytes after the
entry point (unfortunately I picked a bad address to use) we need to
go 0x8 bytes offset into this data
01 10 81 e2 01 20 82 e2
00001008 <main>:
1008: e2811001 add r1, r1, #1
100c: e2822001 add r2, r2, #1
1010: e2833001 add r3, r3, #1
this is all very file dependent, the cpu could care less about labels, main only means something to the humans, not the cpu.
If I convert the elf into other formats which are perfectly executable:
motorola s record:
S00A0000736F2E7372656338
S1131000000000EBFEFFFFEA011081E2012082E212
S10F1010013083E2014084E2FAFFFFEAB1
S9031000EC
raw binary image
hexdump -C so.bin
00000000 00 00 00 eb fe ff ff ea 01 10 81 e2 01 20 82 e2 |............. ..|
00000010 01 30 83 e2 01 40 84 e2 fa ff ff ea |.0...#......|
0000001c
The instruction bytes of interest are of course there, but the symbol information isnt. It depends on the file format you are interested in as to 1) if you can find "main" and then 2) print out the first few bytes at that address.
Hmm, a bit disturbing, but if you link for 0x2000 gnu ld burns some disk space and puts the offset at 0x2000, but choose 0x20000000 and it burns more disk space but not as much
000100d0 2f 00 00 00 08 00 00 20 00 00 00 00 10 00 01 00
shows the file offset is 0x010010 but the address in target space is 0x20000008
00010010 01 30 83 e2 01 40 84 e2 fa ff ff ea 41 11 00 00
00010020 00 61 65 61 62 69 00 01 07 00 00 00 08 01
just to demonstrate/enforce the file offset and the target memory space address are two different things.
this is a very nice format for what you are wanting to do
arm-none-eabi-objcopy -O symbolsrec so.elf so.srec
cat so.srec
$$ so.srec
$a $20000000
_bss_end__ $2001001c
__bss_start__ $2001001c
__bss_end__ $2001001c
_start $20000000
__bss_start $2001001c
main $20000008
__end__ $2001001c
_edata $2001001c
_end $2001001c
_stack $80000
__data_start $2001001c
$$
S0090000736F2E686578A1
S31520000000000000EBFEFFFFEA011081E2012082E200
S31120000010013083E2014084E2FAFFFFEA9F
S70520000000DA

Pulling individual integer value from hexadecimal value

Here is my hex code:
42 4D C6 00 00 00 00 00 00 00 76 00 00 00 28 00
00 00 0A 00 00 00 0A 00 00 00 01 00 04 00 00 00
00 00 50 00 00 00 12 0B 00 00 12 0B 00 00 10 00
00 00 10 00 00 00 FF 00 00 00 00 FF 00 00 00 00
42 00 5A 5A 84 00 00 00 FF 00 FF 00 FF 00 00 FF
FF 00 08 FF FF 00 5A FF FF 00 FF FF FF 00 FF FF
FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 FF FF
FF 00 FF FF FF 00 92 59 00 16 47 00 00 00 25 90
01 64 61 00 00 00 59 90 11 64 61 00 00 00 99 00
16 48 11 00 00 00 90 01 64 61 11 00 00 00 00 16
64 61 00 00 00 00 01 16 46 10 09 00 00 00 11 64
41 00 99 00 00 00 16 64 11 09 95 00 00 00 66 48
10 09 53 00 00 00
I know that the pixel "assignment" starts with the first line being (10 pixels wide):
92 59 00 16 47 00 00 00
I need to count how many times each colour is in the image, but I am unable to pull the individual integer value (ie: just the 9, then just the 2, then just the 5, and so on). The only value I am able to pull is "92" then "59" then "00"...
This is my code for that segment (the offset is 118 and the total hex values remaining are 80):
int nbr_each[NBRCOLOURS];
int ch, pixel;
fseek(fptr, 118, SEEK_SET);
for (count = 0; count < 81; count++)
{
pixel = fgetc(fptr);
nbr_each[pixel] = nbr_each[pixel] + 1;
}
fgetc will get you the individual characters.
first = fgetc(fptr); // '9'
second = fgetc(fptr); // '2'
space = fgetc(fptr); // ' '
Then convert each digit to a number 0..9 by subtracting off '0':
first -= '0';
second -= '0';
Then to count each digit, something like this:
nbr_each[first]++;
nbr_each[second]++;

SSPI and SQL Server Windows Authentication

I'm trying to connect to SQL Server with Windows Authentication. Microsoft C# and C sources can be found at NetCpp.
In Delphi I have code like this:
function TTDS7SSPI.MakeSPN: string;
const
szBracketedInstanceFormatString = '%s/[%s]:%s';
szBracketedEmptyInstanceFormatString = '%s/[%s]%s';
szClearInstanceFormatString = '%s/%s:%s';
szClearEmptyInstanceFormatString = '%s/%s%s';
szBracketedFormatString = '%s/[%s]:%d';
szClearFormatString = '%s/%s:%d';
var
NeedBrackets: Boolean;
FmtString: string;
begin
NeedBrackets := Pos(':', FHostName) > 0;
if FInstanceName <> '' then begin
// Make an instance name based SPN, i.e. MSSQLSvc/FQDN:instancename
if NeedBrackets then begin
if FInstanceName = '' then
FmtString := szBracketedEmptyInstanceFormatString
else
FmtString := szBracketedInstanceFormatString;
end
else begin
if FInstanceName = '' then
FmtString := szClearEmptyInstanceFormatString
else
FmtString := szClearInstanceFormatString;
end;
Result := Format(FmtString, [SQL_SERVICECLASS, FHostName, FInstanceName]);
end
else begin
// Make a TCP port based SPN, i.e. MSSQLSvc/FQDN:TcpPort
Assert(FPort > 0);
if NeedBrackets then
FmtString := szBracketedFormatString
else
FmtString := szClearFormatString;
Result := Format(FmtString, [SQL_SERVICECLASS, FHostName, FPort]);
end;
end;
function TTDS7SSPI.GetAuth: TBytes;
var
pkgInfo: PSecPkgInfo;
SecBuf: SecBuffer;
BuffDesc: SecBufferDesc;
status: SECURITY_STATUS;
attrs: Cardinal;
tsExpiry: TTimeStamp;
const
NEG_STR: WideString = 'Negotiate'; // 'NTLM'; // 'Kerberos';
begin
Result := nil;
status := QuerySecurityPackageInfo({$IFDEF FPC}PSecChar{$ELSE}PSecWChar{$ENDIF}(NEG_STR), pkgInfo);
if status <> SEC_E_OK then
raise Exception.CreateFmt('Couldn''t query package info for %s, error %X', [NEG_STR, status]);
FMaxMessageLen := pkgInfo.cbMaxToken; // 4096;
FreeContextBuffer(pkgInfo);
TTimeStamp(tsExpiry).QuadPart := 0;
status := AcquireCredentialsHandle(nil, {$IFDEF FPC}PSecChar{$ELSE}PSecWChar{$ENDIF}(NEG_STR), SECPKG_CRED_BOTH, // SECPKG_CRED_OUTBOUND
nil, nil, nil, nil, #FCred, tsExpiry); // tsExpiry as var parameter
if status <> SEC_E_OK then
raise Exception.CreateFmt('AcquireCredentialsHandle error %X', [status]);
BuffDesc.ulVersion := SECBUFFER_VERSION;
BuffDesc.cBuffers := 1;
BuffDesc.pBuffers := #SecBuf;
SecBuf.BufferType := SECBUFFER_TOKEN;
SetLength(Result, FMaxMessageLen);
SecBuf.pvBuffer := #Result[0];
SecBuf.cbBuffer := FMaxMessageLen;
{status := QueryCredentialsAttributes(#FCred, SECPKG_CRED_ATTR_NAMES, #attrName);
if status = SEC_E_OK then
FSPN := PWideChar(attrName.sUserName)
else}
// For DAC use "localhost" instead of the server name (Microsoft)
FSPN := WideString(MakeSPN);
FContextAttrib := ISC_REQ_DELEGATE or ISC_REQ_MUTUAL_AUTH or ISC_REQ_INTEGRITY or ISC_REQ_EXTENDED_ERROR;
// ISC_REQ_CONFIDENTIALITY or ISC_REQ_REPLAY_DETECT or ISC_REQ_CONNECTION;
// $8C03C;
// ISC_REQ_MUTUAL_AUTH or ISC_REQ_IDENTIFY or ISC_REQ_CONFIDENTIALITY or ISC_REQ_REPLAY_DETECT or ISC_REQ_SEQUENCE_DETECT or ISC_REQ_CONNECTION or ISC_REQ_DELEGATE;
status := InitializeSecurityContext(#FCred, nil, {$IFDEF FPC}PSecChar{$ELSE}PSecWChar{$ENDIF}(FSPN),
FContextAttrib,
0, SECURITY_NATIVE_DREP, nil, 0, #FCredCtx, #BuffDesc, attrs, #tsExpiry);
if status <= 0 then
raise Exception.CreateFmt('InitializeSecurityContext error %X', [status]);
if (status = SEC_I_COMPLETE_NEEDED) or (status = SEC_I_COMPLETE_AND_CONTINUE) {or (status = SEC_I_CONTINUE_NEEDED)} then begin
status := CompleteAuthToken(#FCredCtx, #BuffDesc);
if status <> SEC_E_OK then begin
FreeCredentialsHandle(#FCred);
Result := nil;
raise Exception.CreateFmt('CompleteAuthToken error %X', [status]);
end;
end
else if (status <> SEC_E_OK) and (status <> SEC_I_CONTINUE_NEEDED) then begin
// SEC_I_CONTINUE_NEEDED
// The client must send the output token to the server and wait for a return token.
// The returned token is then passed in another call to InitializeSecurityContext (Negotiate). The output token can be empty
FreeCredentialsHandle(#FCred);
Result := nil;
raise Exception.CreateFmt('InitializeSecurityContext error %X', [status]);
end;
SetLength(Result, SecBuf.cbBuffer);
end;
function TTDS7SSPI.ParseServerResponse(Buf: TBytes): TBytes;
var
InSecBuff, OutSecBuff: SecBuffer;
InBuffDesc, OutBuffDesc: SecBufferDesc;
status: SECURITY_STATUS;
attrs: Cardinal;
tsExpiry: TTimeStamp;
begin
Assert((Length(Buf) >= 32) or (Length(Buf) <= Integer(FMaxMessageLen)));
InBuffDesc.ulVersion := SECBUFFER_VERSION;
InBuffDesc.cBuffers := 1;
InBuffDesc.pBuffers := #InSecBuff;
OutBuffDesc.ulVersion := SECBUFFER_VERSION;
OutBuffDesc.cBuffers := 1;
OutBuffDesc.pBuffers := #OutSecBuff;
Assert(Length(Buf) > 0);
InSecBuff.BufferType := SECBUFFER_TOKEN;
InSecBuff.pvBuffer := #Buf[0];
InSecBuff.cbBuffer := Length(Buf);
OutSecBuff.BufferType := SECBUFFER_TOKEN;
SetLength(Result, FMaxMessageLen);
OutSecBuff.pvBuffer := #Result[0];
OutSecBuff.cbBuffer := Length(Result);
status := InitializeSecurityContext(#FCred, #FCredCtx, {$IFDEF FPC}PSecChar{$ELSE}PSecWChar{$ENDIF}(FSPN),
FContextAttrib,
0, SECURITY_NATIVE_DREP, #InBuffDesc, 0, #FCredCtx, #OutBuffDesc, attrs, #tsExpiry);
if status <> SEC_E_OK then begin
Result := nil;
raise Exception.CreateFmt('InitializeSecurityContext error %X', [status]);
end
else
SetLength(Result, OutSecBuff.cbBuffer);
end;
The SPN I got is like MSSQLSvc/3R-XP:MSSQL2008 (client and server both on 3R-XP, instance MSSQL2008). InitializeSecurityContext has status SEC_I_CONTINUE_NEEDED. Everything works without errors except that the server does not return any of the rows from the query, only TDS_DONE.
The SQL Server log says:
Login succeeded for user '3R-XP\me'. Connection made using Windows authentication. [CLIENT: 192.168.0.100]
Also I tried to compare OLEDB and mine data sent and received. I can't see the first packet sent by OLEDB due to SSL encryption. Mine SSPI login data
4E 54 4C 4D 53 53 | NTLMSS
50 00 01 00 00 00 97 B2 08 E2 09 00 09 00 2D 00 | P.............-.
00 00 05 00 05 00 28 00 00 00 05 01 28 0A 00 00 | ......(.....(...
00 0F 33 52 2D 58 50 57 4F 52 4B 47 52 4F 55 50 | ..3R-XPWORKGROUP
The server response of OLEDB (connect to another PC due to the fact that WinPCAP can only work with real adapters, so the host name is 'hp-6320' and the client name is '3R-Win7' here) is:
000000 04 01 00 A5 00 00 01 00 ED 9A 00 4E 54 4C 4D 53 | ...........NTLMS
000010 53 50 00 02 00 00 00 0E 00 0E 00 38 00 00 00 15 | SP.........8....
000020 82 8A E2 A3 6E FC 4B 59 86 13 D6 00 00 00 00 00 | ....n.KY........
000030 00 00 00 54 00 54 00 46 00 00 00 05 01 28 0A 00 | ...T.T.F.....(..
000040 00 00 0F 48 00 50 00 2D 00 36 00 33 00 32 00 30 | ...H.P.-.6.3.2.0
000050 00 02 00 0E 00 48 00 50 00 2D 00 36 00 33 00 32 | .....H.P.-.6.3.2
000060 00 30 00 01 00 0E 00 48 00 50 00 2D 00 36 00 33 | .0.....H.P.-.6.3
000070 00 32 00 30 00 04 00 0E 00 68 00 70 00 2D 00 36 | .2.0.....h.p.-.6
000080 00 33 00 32 00 30 00 03 00 0E 00 68 00 70 00 2D | .3.2.0.....h.p.-
000090 00 36 00 33 00 32 00 30 00 06 00 04 00 01 00 00 | .6.3.2.0........
0000A0 00 00 00 00 00 | .....
SQL Server response with my code (machine '3R-XP')
04 01 00 89 00 00 01 00 | ........
ED 7E 00 4E 54 4C 4D 53 53 50 00 02 00 00 00 0A | .~.NTLMSSP......
00 0A 00 38 00 00 00 15 C2 8A E2 B0 17 7A 15 A4 | ...8.........z..
21 2A 96 38 E6 3D 01 00 00 00 00 3C 00 3C 00 42 | !*.8.=.....<.<.B
00 00 00 05 01 28 0A 00 00 00 0F 33 00 52 00 2D | .....(.....3.R.-
00 58 00 50 00 02 00 0A 00 33 00 52 00 2D 00 58 | .X.P.....3.R.-.X
00 50 00 01 00 0A 00 33 00 52 00 2D 00 58 00 50 | .P.....3.R.-.X.P
00 04 00 0A 00 33 00 52 00 2D 00 58 00 50 00 03 | .....3.R.-.X.P..
00 0A 00 33 00 52 00 2D 00 58 00 50 00 00 00 00 | ...3.R.-.X.P....
00 | .
It looks the same. But after that second InitializeSecurityContext OLEDB returns the value
000000 11 01 01 A2 00 00 01 00 4E 54 4C 4D 53 53 50 00 | ........NTLMSSP.
000010 03 00 00 00 18 00 18 00 78 00 00 00 FA 00 FA 00 | ........x.......
000020 90 00 00 00 0E 00 0E 00 58 00 00 00 04 00 04 00 | ........X.......
000030 66 00 00 00 0E 00 0E 00 6A 00 00 00 10 00 10 00 | f.......j.......
000040 8A 01 00 00 15 82 88 E2 06 01 B1 1D 00 00 00 0F | ................
000050 18 B1 57 6E 0F 9B BE 6A AF 2A D4 76 8D B2 19 72 | ..Wn...j.*.v...r
000060 33 00 52 00 2D 00 57 00 69 00 6E 00 37 00 6D 00 | 3.R.-.W.i.n.7.m.
000070 65 00 33 00 52 00 2D 00 57 00 49 00 4E 00 37 00 | e.3.R.-.W.I.N.7.
000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
000090 00 00 00 00 00 00 00 00 3B 97 82 77 95 74 1E 7C | ........;..w.t.|
0000A0 A8 D1 C5 2F 5F 82 7A 9C 01 01 00 00 00 00 00 00 | .../_.z.........
0000B0 EE 4C 92 1E 68 10 D1 01 B3 93 23 3B A9 14 0C EF | .L..h.....#;....
0000C0 00 00 00 00 02 00 0E 00 48 00 50 00 2D 00 36 00 | ........H.P.-.6.
0000D0 33 00 32 00 30 00 01 00 0E 00 48 00 50 00 2D 00 | 3.2.0.....H.P.-.
0000E0 36 00 33 00 32 00 30 00 04 00 0E 00 68 00 70 00 | 6.3.2.0.....h.p.
0000F0 2D 00 36 00 33 00 32 00 30 00 03 00 0E 00 68 00 | -.6.3.2.0.....h.
000100 70 00 2D 00 36 00 33 00 32 00 30 00 06 00 04 00 | p.-.6.3.2.0.....
000110 01 00 00 00 08 00 30 00 30 00 00 00 00 00 00 00 | ......0.0.......
000120 01 00 00 00 00 20 00 00 9B 51 53 D8 0E 0F C8 EB | ..... ...QS.....
000130 F9 11 AB 3D B3 FB 86 F6 D0 D2 97 3C 4C F7 E0 48 | ...=.......<L..H
000140 C4 BF 2F 60 DC CA AB 10 0A 00 10 00 14 5E 11 19 | ../`.........^..
000150 42 DC 79 32 B1 DC 04 C0 C9 48 8D 2C 09 00 2A 00 | B.y2.....H.,..*.
000160 4D 00 53 00 53 00 51 00 4C 00 53 00 76 00 63 00 | M.S.S.Q.L.S.v.c.
000170 2F 00 68 00 70 00 2D 00 36 00 33 00 32 00 30 00 | /.h.p.-.6.3.2.0.
000180 3A 00 31 00 34 00 33 00 33 00 00 00 00 00 00 00 | :.1.4.3.3.......
000190 00 00 7D 45 28 4F E6 4B 38 90 BD F6 91 61 A7 E8 | ..}E(O.K8....a..
0001A0 8D 26 | .&
while for my code it returns
11 01 00 50 00 00 00 00 4E 54 4C 4D 53 53 50 00 | ...P....NTLMSSP.
03 00 00 00 00 00 00 00 48 00 00 00 00 00 00 00 | ........H.......
48 00 00 00 00 00 00 00 48 00 00 00 00 00 00 00 | H.......H.......
48 00 00 00 00 00 00 00 48 00 00 00 00 00 00 00 | H.......H.......
48 00 00 00 15 C2 88 E2 05 01 28 0A 00 00 00 0F | H.........(.....
As you can see all structures are empty (size 0, allocated 0, offset 48). Is there something wrong? How to fix that stuff? I've tried different flags etc already, the results are the same or even worse. OLEDB works so it seems that the server is configured properly.
With WinAPIOverride I found that authentication uses Bindings (see QueryContextAttributes SECPKG_ATTR_UNIQUE_BINDINGS) retrieved from SSL handshake in negotiation InitializeSecurityContext as SECBUFFER_CHANNEL_BINDINGS member.
So far I made SSPI based SSL handshake, got Bindings that looks like
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 17 00 00 00 20 00 00 00 | ............ ...
74 6C 73 2D 75 6E 69 71 75 65 3A 66 55 6F 05 7F | tls-unique:fUo.
DD 90 31 4F 87 02 52 | ..1O..R
found that those empty NTLMSSP message seems proper (with some extra at the end) while client and server on same machine, ODBC driver sends like
A1 77 30 75 A0 03 0A 01 01 A2 5A 04 58 4E 54 4C .w0u......Z.XNTL
4D 53 53 50 00 03 00 00 00 00 00 00 00 58 00 00 MSSP.........X..
00 00 00 00 00 58 00 00 00 00 00 00 00 58 00 00 .....X.......X..
00 00 00 00 00 58 00 00 00 00 00 00 00 58 00 00 .....X.......X..
00 00 00 00 00 58 00 00 00 15 C2 88 E2 0A 00 5A .....X.........Z
29 00 00 00 0F 9E 3F 5C EE FF F1 AF 9A 44 4C 3A ).....?\.....DL:
6F C3 20 0F 8B A3 12 04 10 01 00 00 00 9C B1 60 o. ............`
36 3B 84 96 09 00 00 00 00 6;.......
remote last authentication data looks like (ODBC driver)
4E 54 4C 4D 53 53 50 00 03 00 00 00 18 00 18 00 NTLMSSP.........
78 00 00 00 3C 01 3C 01 90 00 00 00 0E 00 0E 00 x...<.<.........
58 00 00 00 04 00 04 00 66 00 00 00 0E 00 0E 00 X.......f.......
6A 00 00 00 10 00 10 00 CC 01 00 00 15 82 88 E2 j...............
0A 00 5A 29 00 00 00 0F E0 87 5F 85 21 5A 73 17 ..Z)......_.!Zs.
04 6C 1A F5 9C BA F7 42 33 00 52 00 2D 00 57 00 .l.....B3.R.-.W.
69 00 6E 00 37 00 6D 00 65 00 33 00 52 00 2D 00 i.n.7.m.e.3.R.-.
57 00 49 00 4E 00 37 00 00 00 00 00 00 00 00 00 W.I.N.7.........
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
37 F2 38 62 5B 9C 7E 07 6F 89 9F 33 B2 92 3C 5C 7.8b[.~.o..3..<\
01 01 00 00 00 00 00 00 47 39 01 AD AC 4F D1 01 ........G9...O..
0D 36 47 06 7E 70 B8 A4 00 00 00 00 02 00 18 00 .6G.~p..........
48 00 50 00 2D 00 45 00 4C 00 49 00 54 00 45 00 H.P.-.E.L.I.T.E.
42 00 4F 00 4F 00 4B 00 01 00 18 00 B.O.O.K.....
while SSPI with Bindings looks slightly bigger (8 first bytes here is TDS packet header)
11 01 01 EE 00 00 00 00 4E 54 4C 4D 53 53 50 00 | ........NTLMSSP.
03 00 00 00 18 00 18 00 78 00 00 00 46 01 46 01 | ........x...F.F.
90 00 00 00 0E 00 0E 00 58 00 00 00 04 00 04 00 | ........X.......
66 00 00 00 0E 00 0E 00 6A 00 00 00 10 00 10 00 | f.......j.......
D6 01 00 00 15 82 88 E2 0A 00 5A 29 00 00 00 0F | ..........Z)....
AD A5 C9 05 8C 25 E1 A9 C5 3E 17 BD 3D 19 E3 EB | .....%...>..=...
33 00 52 00 2D 00 57 00 69 00 6E 00 37 00 6D 00 | 3.R.-.W.i.n.7.m.
65 00 33 00 52 00 2D 00 57 00 49 00 4E 00 37 00 | e.3.R.-.W.I.N.7.
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 02 0B C5 A2 01 17 DB AC | ................
D8 26 9E 1B AF A1 77 32 01 01 00 00 00 00 00 00 | .&....w2........
B8 28 90 0F AD 4F D1 01 41 F1 DF 7C BE 85 5D B6 | .(...O..A..|..].
00 00 00 00 02 00 18 00 48 00 50 00 2D 00 45 00 | ........H.P.-.E.
4C 00 49 00 54 00 45 00 42 00 4F 00 4F 00 4B 00 | L.I.T.E.B.O.O.K.
01 00 18 00 48 00 50 00 2D 00 45 00 4C 00 49 00 | ....H.P.-.E.L.I.
54 00 45 00 42 00 4F 00 4F 00 4B 00 04 00 18 00 | T.E.B.O.O.K.....
48 00 50 00 2D 00 45 00 6C 00 69 00 74 00 65 00 | H.P.-.E.l.i.t.e.
62 00 6F 00 6F 00 6B 00 03 00 18 00 48 00 50 00 | b.o.o.k.....H.P.
2D 00 45 00 6C 00 69 00 74 00 65 00 62 00 6F 00 | -.E.l.i.t.e.b.o.
6F 00 6B 00 07 00 08 00 B8 28 90 0F AD 4F D1 01 | o.k......(...O..
06 00 04 00 02 00 00 00 08 00 30 00 30 00 00 00 | ..........0.0...
00 00 00 00 01 00 00 00 00 20 00 00 DC 75 9C 98 | ......... ...u..
70 C7 28 D7 BC C7 1E 14 48 70 0E 3B 8B A4 94 7C | p.(.....Hp.;...|
32 05 44 FD 85 5F D3 54 DB 6C 84 22 0A 00 10 00 | 2.D.._.T.l."....
B1 3B 92 CC 6C 5B E2 CD 0F 24 19 5F 6F 73 47 73 | .;..l[...$._osGs
09 00 3E 00 4D 00 53 00 53 00 51 00 4C 00 53 00 | ..>.M.S.S.Q.L.S.
76 00 63 00 2F 00 48 00 50 00 2D 00 45 00 4C 00 | v.c./.H.P.-.E.L.
49 00 54 00 45 00 42 00 4F 00 4F 00 4B 00 3A 00 | I.T.E.B.O.O.K.:.
4D 00 53 00 53 00 51 00 4C 00 32 00 30 00 30 00 | M.S.S.Q.L.2.0.0.
38 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 46 | 8..............F
20 EB 45 EC C8 67 9F E3 45 45 9C 79 76 47 | .E..g..EE.yvG
QueryContextAttributes(#FCtxHandle, SECPKG_ATTR_NEGOTIATION_INFO, #NegInfo) returns state SECPKG_NEGOTIATION_COMPLETE so everything suppose to be fine, server log shows that "Authentication successful" but there is still not enough rights to get results of queries or server errors like "Cannot find the object "all_types" because it does not exist or you do not have permissions" while simple queries like "SET LOCK TIMEOUT 100" runs without errors.
So my thoughts that Windows Authentication in the eyes of own creator doesn't looks secure enough to allow it to some third-party applications. Guest account enabled and have permissions to read/write data and it works through ODBC driver.

How does raw result format returned from Microsoft SQL Server looks like?

I have been using SQL for like 10 years but now I realised I never knew how the client actually receive and process data it gets from the server.
My question is, how does the result from Microsoft SQL Server actually look like in raw format? The same as that result from HTTP server contains HTTP headers and a Content-Type header to tell what the body format is (mostly HTML for web pages).
The protocol name is TDS (Tabular Data Stream).
Some documentation is available at MSDN.
There is a very basic example of data being transferred for simple query select 'foo' as 'bar'
Request
Packet header (type, legth, etc)
01 01 00 5C 00 00 01 00
Packet data
16 00 00 00 - headers total length
12 00 00 00 - first header length
02 00 - type
00 00 00 00 00 00 00 01 00 00 00 00 - data
0A 00 73 00 65 00 6C 00 65 00 63 00 74 00 20 00
27 00 66 00 6F 00 6F 00 27 00 20 00 61 00 73 00
20 00 27 00 62 00 61 00 72 00 27 00 0A 00 20 00
20 00 20 00 20 00 20 00 20 00 20 00 20 00 - sql
Response
Packet header (type, legth, etc)
04 01 00 33 00 00 01 00
Packet data
columns metadata
81 - record id
01 - count
first column
00 00 00 00 00 - user type
20 00 - flags
A7 - type
03 00 - length
09 04 D0 00 34 - colation
03 - column name length
62 00 61 00 72 00 - column name bytes
rows
D1 - record id
03 00 - length
66 6F 6F - value
ending data
FD - record id
10 00 - status
C1 00
01 00 00 00 00 00 00 00 - rows total
We can also look at parser implementation thanks to reference sources.

Resources