1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
|
<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>SAMBA Developers Guide</title><link rel="stylesheet" href="samba.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.60.1"><meta name="description" content="
Last Update : Fri Jun 6 00:45:54 CEST 2003
This book is a collection of documents that might be useful for
people developing samba or those interested in doing so.
It's nothing more than a collection of documents written by samba developers about
the internals of various parts of samba and the SMB protocol. It's still incomplete.
The most recent version of this document
can be found at http://devel.samba.org/.
Please send updates to Jelmer Vernooij.
This documentation is distributed under the GNU General Public License (GPL)
version 2. A copy of the license is included with the Samba source
distribution. A copy can be found on-line at http://www.fsf.org/licenses/gpl.txt
"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="book" lang="en"><div class="titlepage"><div><div><h1 class="title"><a name="Samba-Developers-Guide"></a>SAMBA Developers Guide</h1></div><div><div class="abstract"><p class="title"><b>Abstract</b></p><p>
<span class="emphasis"><em>Last Update</em></span> : Fri Jun 6 00:45:54 CEST 2003
</p><p>
This book is a collection of documents that might be useful for
people developing samba or those interested in doing so.
It's nothing more than a collection of documents written by samba developers about
the internals of various parts of samba and the SMB protocol. It's still incomplete.
The most recent version of this document
can be found at <ulink url="http://devel.samba.org/">http://devel.samba.org/</ulink>.
Please send updates to <ulink url="mailto:jelmer@samba.org">Jelmer Vernooij</ulink>.
</p><p>
This documentation is distributed under the GNU General Public License (GPL)
version 2. A copy of the license is included with the Samba source
distribution. A copy can be found on-line at <ulink url="http://www.fsf.org/licenses/gpl.txt">http://www.fsf.org/licenses/gpl.txt</ulink>
</p></div></div></div><div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><a href="#id2800193">Attributions</a></dt><dt>1. <a href="#netbios">Definition of NetBIOS Protocol and Name Resolution Modes</a></dt><dd><dl><dt><a href="#id2802605">NETBIOS</a></dt><dt><a href="#id2796596">BROADCAST NetBIOS</a></dt><dt><a href="#id2796627">NBNS NetBIOS</a></dt></dl></dd><dt>2. <a href="#architecture">Samba Architecture</a></dt><dd><dl><dt><a href="#id2796741">Introduction</a></dt><dt><a href="#id2799372">Multithreading and Samba</a></dt><dt><a href="#id2799410">Threading smbd</a></dt><dt><a href="#id2799485">Threading nmbd</a></dt><dt><a href="#id2799552">nbmd Design</a></dt></dl></dd><dt>3. <a href="#debug">The samba DEBUG system</a></dt><dd><dl><dt><a href="#id2796926">New Output Syntax</a></dt><dt><a href="#id2797071">The DEBUG() Macro</a></dt><dt><a href="#id2797201">The DEBUGADD() Macro</a></dt><dt><a href="#id2797246">The DEBUGLVL() Macro</a></dt><dt><a href="#id2797357">New Functions</a></dt><dd><dl><dt><a href="#id2797364">dbgtext()</a></dt><dt><a href="#id2797383">dbghdr()</a></dt><dt><a href="#id2797406">format_debug_text()</a></dt></dl></dd></dl></dd><dt>4. <a href="#CodingSuggestions">Coding Suggestions</a></dt><dt>5. <a href="#internals">Samba Internals</a></dt><dd><dl><dt><a href="#id2799193">Character Handling</a></dt><dt><a href="#id2799218">The new functions</a></dt><dt><a href="#id2852640">Macros in byteorder.h</a></dt><dd><dl><dt><a href="#id2852653">CVAL(buf,pos)</a></dt><dt><a href="#id2852667">PVAL(buf,pos)</a></dt><dt><a href="#id2852680">SCVAL(buf,pos,val)</a></dt><dt><a href="#id2852694">SVAL(buf,pos)</a></dt><dt><a href="#id2852710">IVAL(buf,pos)</a></dt><dt><a href="#id2852724">SVALS(buf,pos)</a></dt><dt><a href="#id2852738">IVALS(buf,pos)</a></dt><dt><a href="#id2852753">SSVAL(buf,pos,val)</a></dt><dt><a href="#id2852767">SIVAL(buf,pos,val)</a></dt><dt><a href="#id2852782">SSVALS(buf,pos,val)</a></dt><dt><a href="#id2852796">SIVALS(buf,pos,val)</a></dt><dt><a href="#id2852810">RSVAL(buf,pos)</a></dt><dt><a href="#id2852825">RIVAL(buf,pos)</a></dt><dt><a href="#id2852839">RSSVAL(buf,pos,val)</a></dt><dt><a href="#id2852851">RSIVAL(buf,pos,val)</a></dt></dl></dd><dt><a href="#id2852867">LAN Manager Samba API</a></dt><dd><dl><dt><a href="#id2852903">Parameters</a></dt><dt><a href="#id2858884">Return value</a></dt></dl></dd><dt><a href="#id2858969">Code character table</a></dt></dl></dd><dt>6. <a href="#parsing">The smb.conf file</a></dt><dd><dl><dt><a href="#id2859088">Lexical Analysis</a></dt><dd><dl><dt><a href="#id2859179">Handling of Whitespace</a></dt><dt><a href="#id2859235">Handling of Line Continuation</a></dt><dt><a href="#id2859300">Line Continuation Quirks</a></dt></dl></dd><dt><a href="#id2859396">Syntax</a></dt><dd><dl><dt><a href="#id2858239">About params.c</a></dt></dl></dd></dl></dd><dt>7. <a href="#unix-smb">NetBIOS in a Unix World</a></dt><dd><dl><dt><a href="#id2858286">Introduction</a></dt><dt><a href="#id2858311">Usernames</a></dt><dt><a href="#id2858381">File Ownership</a></dt><dt><a href="#id2858418">Passwords</a></dt><dt><a href="#id2858463">Locking</a></dt><dt><a href="#id2858525">Deny Modes</a></dt><dt><a href="#id2858555">Trapdoor UIDs</a></dt><dt><a href="#id2858580">Port numbers</a></dt><dt><a href="#id2858634">Protocol Complexity</a></dt></dl></dd><dt>8. <a href="#tracing">Tracing samba system calls</a></dt><dt>9. <a href="#windows-debug">Finding useful information on windows</a></dt><dd><dl><dt><a href="#id2869073">Netlogon debugging output</a></dt></dl></dd><dt>10. <a href="#ntdomain">NT Domain RPC's</a></dt><dd><dl><dt><a href="#id2869214">Introduction</a></dt><dd><dl><dt><a href="#id2869414">Sources</a></dt><dt><a href="#id2869450">Credits</a></dt></dl></dd><dt><a href="#id2869488">Notes and Structures</a></dt><dd><dl><dt><a href="#id2869495">Notes</a></dt><dt><a href="#id2869570">Enumerations</a></dt><dt><a href="#id2869784">Structures</a></dt></dl></dd><dt><a href="#id2872733">MSRPC over Transact Named Pipe</a></dt><dd><dl><dt><a href="#id2872746">MSRPC Pipes</a></dt><dt><a href="#id2872849">Header</a></dt><dt><a href="#id2873718">Tail</a></dt><dt><a href="#id2873764">RPC Bind / Bind Ack</a></dt><dt><a href="#id2873945">NTLSA Transact Named Pipe</a></dt><dt><a href="#id2874109">LSA Open Policy</a></dt><dt><a href="#id2874235">LSA Query Info Policy</a></dt><dt><a href="#id2874342">LSA Enumerate Trusted Domains</a></dt><dt><a href="#id2874433">LSA Open Secret</a></dt><dt><a href="#id2874543">LSA Close</a></dt><dt><a href="#id2874608">LSA Lookup SIDS</a></dt><dt><a href="#id2874818">LSA Lookup Names</a></dt></dl></dd><dt><a href="#id2867818">NETLOGON rpc Transact Named Pipe</a></dt><dd><dl><dt><a href="#id2867980">LSA Request Challenge</a></dt><dt><a href="#id2868114">LSA Authenticate 2</a></dt><dt><a href="#id2868261">LSA Server Password Set</a></dt><dt><a href="#id2868376">LSA SAM Logon</a></dt><dt><a href="#id2868479">LSA SAM Logoff</a></dt></dl></dd><dt><a href="#id2868571">\\MAILSLOT\NET\NTLOGON</a></dt><dd><dl><dt><a href="#id2868583">Query for PDC</a></dt><dt><a href="#id2868850">SAM Logon</a></dt></dl></dd><dt><a href="#id2877631">SRVSVC Transact Named Pipe</a></dt><dd><dl><dt><a href="#id2877676">Net Share Enum</a></dt><dt><a href="#id2877896">Net Server Get Info</a></dt></dl></dd><dt><a href="#id2878012">Cryptographic side of NT Domain Authentication</a></dt><dd><dl><dt><a href="#id2878020">Definitions</a></dt><dt><a href="#id2878182">Protocol</a></dt><dt><a href="#id2878280">Comments</a></dt></dl></dd><dt><a href="#id2878330">SIDs and RIDs</a></dt><dd><dl><dt><a href="#id2878368">Well-known SIDs</a></dt><dt><a href="#id2878683">Well-known RIDS</a></dt></dl></dd></dl></dd><dt>11. <a href="#printing">Samba Printing Internals</a></dt><dd><dl><dt><a href="#id2878968">Abstract</a></dt><dt><a href="#id2878984">
Printing Interface to Various Back ends
</a></dt><dt><a href="#id2879080">
Print Queue TDB's
</a></dt><dt><a href="#id2879295">
ChangeID and Client Caching of Printer Information
</a></dt><dt><a href="#id2879308">
Windows NT/2K Printer Change Notify
</a></dt></dl></dd><dt>12. <a href="#wins">Samba WINS Internals</a></dt><dd><dl><dt><a href="#id2879669">WINS Failover</a></dt></dl></dd><dt>13. <a href="#sam">The Upcoming SAM System</a></dt><dd><dl><dt><a href="#id2879798">Security in the 'new SAM'</a></dt><dt><a href="#id2879928">Standalone from UNIX</a></dt><dt><a href="#id2879955">Handles and Races in the new SAM</a></dt><dt><a href="#id2880024">Layers</a></dt><dd><dl><dt><a href="#id2880031">Application</a></dt><dt><a href="#id2880047">SAM Interface</a></dt><dt><a href="#id2880075">SAM Modules</a></dt></dl></dd><dt><a href="#id2880097">SAM Modules</a></dt><dd><dl><dt><a href="#id2880104">Special Module: sam_passdb</a></dt><dt><a href="#id2880122">sam_ads</a></dt></dl></dd><dt><a href="#id2880151">Memory Management</a></dt><dt><a href="#id2880242">Testing</a></dt></dl></dd><dt>14. <a href="#pwencrypt">LanMan and NT Password Encryption</a></dt><dd><dl><dt><a href="#id2880380">Introduction</a></dt><dt><a href="#id2880405">How does it work?</a></dt><dt><a href="#id2880513">The smbpasswd file</a></dt></dl></dd><dt>15. <a href="#modules">Modules</a></dt><dd><dl><dt><a href="#id2880880">Advantages</a></dt><dt><a href="#id2880927">Loading modules</a></dt><dd><dl><dt><a href="#id2880961">Static modules</a></dt><dt><a href="#id2881001">Shared modules</a></dt></dl></dd><dt><a href="#id2881029">Writing modules</a></dt><dd><dl><dt><a href="#id2881090">Static/Shared selection in configure.in</a></dt></dl></dd></dl></dd><dt>16. <a href="#rpc-plugin">RPC Pluggable Modules</a></dt><dd><dl><dt><a href="#id2881286">About</a></dt><dt><a href="#id2881305">General Overview</a></dt></dl></dd><dt>17. <a href="#vfs">VFS Modules</a></dt><dd><dl><dt><a href="#id2881513">The Samba (Posix) VFS layer</a></dt><dd><dl><dt><a href="#id2881520">The general interface</a></dt><dt><a href="#id2881636">Possible VFS operation layers</a></dt></dl></dd><dt><a href="#id2881708">The Interaction between the Samba VFS subsystem and the modules</a></dt><dd><dl><dt><a href="#id2881715">Initialization and registration</a></dt><dt><a href="#id2881898">How the Modules handle per connection data</a></dt></dl></dd><dt><a href="#id2882143">Upgrading to the New VFS Interface</a></dt><dd><dl><dt><a href="#id2882150">Upgrading from 2.2.* and 3.0aplha modules</a></dt></dl></dd><dt><a href="#id2882641">Some Notes</a></dt><dd><dl><dt><a href="#id2882648">Implement TRANSPARENT functions</a></dt><dt><a href="#id2882674">Implement OPAQUE functions</a></dt></dl></dd></dl></dd><dt>18. <a href="#Packaging">Notes to packagers</a></dt><dd><dl><dt><a href="#id2882741">Versioning</a></dt><dt><a href="#id2882774">Modules</a></dt></dl></dd><dt>19. <a href="#contributing">Contributing code</a></dt></dl></div><div class="preface" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="id2800193"></a>Attributions</h2></div></div><div></div></div><p><link linkend="netbios"></p><div class="itemizedlist"><ul type="disc"><li><p>Luke Leighton</p></li></ul></div><p><link linkend="architecture"></p><div class="itemizedlist"><ul type="disc"><li><p>Dan Shearer</p></li></ul></div><p><link linkend="debug"></p><div class="itemizedlist"><ul type="disc"><li><p>Chris Hertel</p></li></ul></div><p><link linkend="CodingSuggestions"></p><div class="itemizedlist"><ul type="disc"><li><p>Steve French</p></li><li><p>Simo Sorce</p></li><li><p>Andrew Bartlett</p></li><li><p>Tim Potter</p></li><li><p>Martin Pool</p></li></ul></div><p><link linkend="internals"></p><div class="itemizedlist"><ul type="disc"><li><p>David Chappell <<ulink url="mailto:David.Chappell@mail.trincoll.edu">David.Chappell@mail.trincoll.edu</ulink>></p></li></ul></div><p><link linkend="parsing"></p><div class="itemizedlist"><ul type="disc"><li><p>Chris Hertel</p></li></ul></div><p><link linkend="unix-smb"></p><div class="itemizedlist"><ul type="disc"><li><p>Andrew Tridgell</p></li></ul></div><p><link linkend="tracing"></p><div class="itemizedlist"><ul type="disc"><li><p>Andrew Tridgell</p></li></ul></div><p><link linkend="windows-debug"></p><div class="itemizedlist"><ul type="disc"><li><p>Jelmer R. Vernooij <<ulink url="mailto:jelmer@samba.org">jelmer@samba.org</ulink>></p></li><li><p>Andrew Tridgell <<ulink url="mailto:tridge@samba.org">tridge@samba.org</ulink>></p></li></ul></div><p><link linkend="ntdomain"></p><div class="itemizedlist"><ul type="disc"><li><p>Luke Leighton <<ulink url="mailto:lkcl@switchboard.net">lkcl@switchboard.net</ulink>></p></li><li><p>Paul Ashton <<ulink url="mailto:paul@argo.demon.co.uk">paul@argo.demon.co.uk</ulink>></p></li><li><p>Duncan Stansfield <<ulink url="mailto:duncans@sco.com">duncans@sco.com</ulink>></p></li></ul></div><p><link linkend="printing"></p><div class="itemizedlist"><ul type="disc"><li><p>Gerald Carter</p></li></ul></div><p><link linkend="wins"></p><div class="itemizedlist"><ul type="disc"><li><p>Gerald Carter</p></li></ul></div><p><link linkend="sam"></p><div class="itemizedlist"><ul type="disc"><li><p>Andrew Bartlett</p></li></ul></div><p><link linkend="pwencrypt"></p><div class="itemizedlist"><ul type="disc"><li><p>Jeremy Allison <<ulink url="mailto:samba@samba.org">samba@samba.org</ulink>></p></li></ul></div><p><link linkend="modules"></p><div class="itemizedlist"><ul type="disc"><li><p>Jelmer Vernooij <<ulink url="mailto:jelmer@samba.org">jelmer@samba.org</ulink>></p></li></ul></div><p><link linkend="rpc-plugin"></p><div class="itemizedlist"><ul type="disc"><li><p>Anthony Liguori <<ulink url="mailto:aliguor@us.ibm.com">aliguor@us.ibm.com</ulink>></p></li><li><p>Jelmer Vernooij <<ulink url="mailto:jelmer@samba.org">jelmer@samba.org</ulink>></p></li></ul></div><p><link linkend="vfs"></p><div class="itemizedlist"><ul type="disc"><li><p>Alexander Bokovoy <<ulink url="mailto:ab@samba.org">ab@samba.org</ulink>></p></li><li><p>Stefan Metzmacher <<ulink url="mailto:metze@metzemix.de">metze@metzemix.de</ulink>></p></li></ul></div><p><link linkend="Packaging"></p><div class="itemizedlist"><ul type="disc"><li><p>Jelmer Vernooij</p></li></ul></div><p><link linkend="contributing"></p><div class="itemizedlist"><ul type="disc"><li><p>Jelmer R. Vernooij <<ulink url="mailto:jelmer@samba.org">jelmer@samba.org</ulink>></p></li></ul></div></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="netbios"></a>Chapter 1. Definition of NetBIOS Protocol and Name Resolution Modes</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Luke</span> <span class="surname">Leighton</span></h3></div></div><div><p class="pubdate">12 June 1997</p></div></div><div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><a href="#id2802605">NETBIOS</a></dt><dt><a href="#id2796596">BROADCAST NetBIOS</a></dt><dt><a href="#id2796627">NBNS NetBIOS</a></dt></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2802605"></a>NETBIOS</h2></div></div><div></div></div><p>
NetBIOS runs over the following tranports: TCP/IP; NetBEUI and IPX/SPX.
Samba only uses NetBIOS over TCP/IP. For details on the TCP/IP NetBIOS
Session Service NetBIOS Datagram Service, and NetBIOS Names, see
rfc1001.txt and rfc1002.txt.
</p><p>
NetBEUI is a raw NetBIOS frame protocol implementation that allows NetBIOS
datagrams to be sent out over the 'wire' embedded within LLC frames.
NetBEUI is not required when using NetBIOS over TCP/IP protocols and it
is preferable NOT to install NetBEUI if it can be avoided.
</p><p>
IPX/SPX is also not required when using NetBIOS over TCP/IP, and it is
preferable NOT to install the IPX/SPX transport unless you are using Novell
servers. At the very least, it is recommended that you do not install
'NetBIOS over IPX/SPX'.
</p><p>
[When installing Windows 95, you will find that NetBEUI and IPX/SPX are
installed as the default protocols. This is because they are the simplest
to manage: no Windows 95 user-configuration is required].
</p><p>
NetBIOS applications (such as samba) offer their services (for example,
SMB file and print sharing) on a NetBIOS name. They must claim this name
on the network before doing so. The NetBIOS session service will then
accept connections on the application's behalf (on the NetBIOS name
claimed by the application). A NetBIOS session between the application
and the client can then commence.
</p><p>
NetBIOS names consist of 15 characters plus a 'type' character. This is
similar, in concept, to an IP address and a TCP port number, respectively.
A NetBIOS-aware application on a host will offer different services under
different NetBIOS name types, just as a host will offer different TCP/IP
services on different port numbers.
</p><p>
NetBIOS names must be claimed on a network, and must be defended. The use
of NetBIOS names is most suitable on a single subnet; a Local Area Network
or a Wide Area Network.
</p><p>
NetBIOS names are either UNIQUE or GROUP. Only one application can claim a
UNIQUE NetBIOS name on a network.
</p><p>
There are two kinds of NetBIOS Name resolution: Broadcast and Point-to-Point.
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2796596"></a>BROADCAST NetBIOS</h2></div></div><div></div></div><p>
Clients can claim names, and therefore offer services on successfully claimed
names, on their broadcast-isolated subnet. One way to get NetBIOS services
(such as browsing: see ftp.microsoft.com/drg/developr/CIFS/browdiff.txt; and
SMB file/print sharing: see cifs4.txt) working on a LAN or WAN is to make
your routers forward all broadcast packets from TCP/IP ports 137, 138 and 139.
</p><p>
This, however, is not recommended. If you have a large LAN or WAN, you will
find that some of your hosts spend 95 percent of their time dealing with
broadcast traffic. [If you have IPX/SPX on your LAN or WAN, you will find
that this is already happening: a packet analyzer will show, roughly
every twelve minutes, great swathes of broadcast traffic!].
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2796627"></a>NBNS NetBIOS</h2></div></div><div></div></div><p>
rfc1001.txt describes, amongst other things, the implementation and use
of, a 'NetBIOS Name Service'. NT/AS offers 'Windows Internet Name Service'
which is fully rfc1001/2 compliant, but has had to take specific action
with certain NetBIOS names in order to make it useful. (for example, it
deals with the registration of <1c> <1d> <1e> names all in different ways.
I recommend the reading of the Microsoft WINS Server Help files for full
details).
</p><p>
The use of a WINS server cuts down on broadcast network traffic for
NetBIOS name resolution. It has the effect of pulling all the broadcast
isolated subnets together into a single NetBIOS scope, across your LAN
or WAN, while avoiding the use of TCP/IP broadcast packets.
</p><p>
When you have a WINS server on your LAN, WINS clients will be able to
contact the WINS server to resolve NetBIOS names. Note that only those
WINS clients that have registered with the same WINS server will be
visible. The WINS server _can_ have static NetBIOS entries added to its
database (usually for security reasons you might want to consider putting
your domain controllers or other important servers as static entries,
but you should not rely on this as your sole means of security), but for
the most part, NetBIOS names are registered dynamically.
</p><p>
This provides some confusion for lots of people, and is worth mentioning
here: a Browse Server is NOT a WINS Server, even if these services are
implemented in the same application. A Browse Server _needs_ a WINS server
because a Browse Server is a WINS client, which is _not_ the same thing].
</p><p>
Clients can claim names, and therefore offer services on successfully claimed
names, on their broadcast-isolated subnet. One way to get NetBIOS services
(such as browsing: see ftp.microsoft.com/drg/developr/CIFS/browdiff.txt; and
SMB file/print sharing: see cifs6.txt) working on a LAN or WAN is to make
your routers forward all broadcast packets from TCP/IP ports 137, 138 and 139.
You will find, however, if you do this on a large LAN or a WAN, that your
network is completely swamped by NetBIOS and browsing packets, which is why
WINS was developed to minimise the necessity of broadcast traffic.
</p><p>
WINS Clients therefore claim names from the WINS server. If the WINS
server allows them to register a name, the client's NetBIOS session service
can then offer services on this name. Other WINS clients will then
contact the WINS server to resolve a NetBIOS name.
</p></div></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="architecture"></a>Chapter 2. Samba Architecture</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Dan</span> <span class="surname">Shearer</span></h3></div></div><div><p class="pubdate"> November 1997</p></div></div><div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><a href="#id2796741">Introduction</a></dt><dt><a href="#id2799372">Multithreading and Samba</a></dt><dt><a href="#id2799410">Threading smbd</a></dt><dt><a href="#id2799485">Threading nmbd</a></dt><dt><a href="#id2799552">nbmd Design</a></dt></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2796741"></a>Introduction</h2></div></div><div></div></div><p>
This document gives a general overview of how Samba works
internally. The Samba Team has tried to come up with a model which is
the best possible compromise between elegance, portability, security
and the constraints imposed by the very messy SMB and CIFS
protocol.
</p><p>
It also tries to answer some of the frequently asked questions such as:
</p><div class="orderedlist"><ol type="1"><li><p>
Is Samba secure when running on Unix? The xyz platform?
What about the root priveliges issue?
</p></li><li><p>Pros and cons of multithreading in various parts of Samba</p></li><li><p>Why not have a separate process for name resolution, WINS, and browsing?</p></li></ol></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2799372"></a>Multithreading and Samba</h2></div></div><div></div></div><p>
People sometimes tout threads as a uniformly good thing. They are very
nice in their place but are quite inappropriate for smbd. nmbd is
another matter, and multi-threading it would be very nice.
</p><p>
The short version is that smbd is not multithreaded, and alternative
servers that take this approach under Unix (such as Syntax, at the
time of writing) suffer tremendous performance penalties and are less
robust. nmbd is not threaded either, but this is because it is not
possible to do it while keeping code consistent and portable across 35
or more platforms. (This drawback also applies to threading smbd.)
</p><p>
The longer versions is that there are very good reasons for not making
smbd multi-threaded. Multi-threading would actually make Samba much
slower, less scalable, less portable and much less robust. The fact
that we use a separate process for each connection is one of Samba's
biggest advantages.
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2799410"></a>Threading smbd</h2></div></div><div></div></div><p>
A few problems that would arise from a threaded smbd are:
</p><div class="orderedlist"><ol type="1"><li><p>
It's not only to create threads instead of processes, but you
must care about all variables if they have to be thread specific
(currently they would be global).
</p></li><li><p>
if one thread dies (eg. a seg fault) then all threads die. We can
immediately throw robustness out the window.
</p></li><li><p>
many of the system calls we make are blocking. Non-blocking
equivalents of many calls are either not available or are awkward (and
slow) to use. So while we block in one thread all clients are
waiting. Imagine if one share is a slow NFS filesystem and the others
are fast, we will end up slowing all clients to the speed of NFS.
</p></li><li><p>
you can't run as a different uid in different threads. This means
we would have to switch uid/gid on _every_ SMB packet. It would be
horrendously slow.
</p></li><li><p>
the per process file descriptor limit would mean that we could only
support a limited number of clients.
</p></li><li><p>
we couldn't use the system locking calls as the locking context of
fcntl() is a process, not a thread.
</p></li></ol></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2799485"></a>Threading nmbd</h2></div></div><div></div></div><p>
This would be ideal, but gets sunk by portability requirements.
</p><p>
Andrew tried to write a test threads library for nmbd that used only
ansi-C constructs (using setjmp and longjmp). Unfortunately some OSes
defeat this by restricting longjmp to calling addresses that are
shallower than the current address on the stack (apparently AIX does
this). This makes a truly portable threads library impossible. So to
support all our current platforms we would have to code nmbd both with
and without threads, and as the real aim of threads is to make the
code clearer we would not have gained anything. (it is a myth that
threads make things faster. threading is like recursion, it can make
things clear but the same thing can always be done faster by some
other method)
</p><p>
Chris tried to spec out a general design that would abstract threading
vs separate processes (vs other methods?) and make them accessible
through some general API. This doesn't work because of the data
sharing requirements of the protocol (packets in the future depending
on packets now, etc.) At least, the code would work but would be very
clumsy, and besides the fork() type model would never work on Unix. (Is there an OS that it would work on, for nmbd?)
</p><p>
A fork() is cheap, but not nearly cheap enough to do on every UDP
packet that arrives. Having a pool of processes is possible but is
nasty to program cleanly due to the enormous amount of shared data (in
complex structures) between the processes. We can't rely on each
platform having a shared memory system.
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2799552"></a>nbmd Design</h2></div></div><div></div></div><p>
Originally Andrew used recursion to simulate a multi-threaded
environment, which use the stack enormously and made for really
confusing debugging sessions. Luke Leighton rewrote it to use a
queuing system that keeps state information on each packet. The
first version used a single structure which was used by all the
pending states. As the initialisation of this structure was
done by adding arguments, as the functionality developed, it got
pretty messy. So, it was replaced with a higher-order function
and a pointer to a user-defined memory block. This suddenly
made things much simpler: large numbers of functions could be
made static, and modularised. This is the same principle as used
in NT's kernel, and achieves the same effect as threads, but in
a single process.
</p><p>
Then Jeremy rewrote nmbd. The packet data in nmbd isn't what's on the
wire. It's a nice format that is very amenable to processing but still
keeps the idea of a distinct packet. See "struct packet_struct" in
nameserv.h. It has all the detail but none of the on-the-wire
mess. This makes it ideal for using in disk or memory-based databases
for browsing and WINS support.
</p></div></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="debug"></a>Chapter 3. The samba DEBUG system</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Chris</span> <span class="surname">Hertel</span></h3></div></div><div><p class="pubdate">July 1998</p></div></div><div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><a href="#id2796926">New Output Syntax</a></dt><dt><a href="#id2797071">The DEBUG() Macro</a></dt><dt><a href="#id2797201">The DEBUGADD() Macro</a></dt><dt><a href="#id2797246">The DEBUGLVL() Macro</a></dt><dt><a href="#id2797357">New Functions</a></dt><dd><dl><dt><a href="#id2797364">dbgtext()</a></dt><dt><a href="#id2797383">dbghdr()</a></dt><dt><a href="#id2797406">format_debug_text()</a></dt></dl></dd></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2796926"></a>New Output Syntax</h2></div></div><div></div></div><p>
The syntax of a debugging log file is represented as:
</p><pre class="programlisting">
>debugfile< :== { >debugmsg< }
>debugmsg< :== >debughdr< '\n' >debugtext<
>debughdr< :== '[' TIME ',' LEVEL ']' FILE ':' [FUNCTION] '(' LINE ')'
>debugtext< :== { >debugline< }
>debugline< :== TEXT '\n'
</pre><p>
TEXT is a string of characters excluding the newline character.
</p><p>
LEVEL is the DEBUG level of the message (an integer in the range
0..10).
</p><p>
TIME is a timestamp.
</p><p>
FILE is the name of the file from which the debug message was
generated.
</p><p>
FUNCTION is the function from which the debug message was generated.
</p><p>
LINE is the line number of the debug statement that generated the
message.
</p><p>Basically, what that all means is:</p><div class="orderedlist"><ol type="1"><li><p>
A debugging log file is made up of debug messages.
</p></li><li><p>
Each debug message is made up of a header and text. The header is
separated from the text by a newline.
</p></li><li><p>
The header begins with the timestamp and debug level of the
message enclosed in brackets. The filename, function, and line
number at which the message was generated follow. The filename is
terminated by a colon, and the function name is terminated by the
parenthesis which contain the line number. Depending upon the
compiler, the function name may be missing (it is generated by the
__FUNCTION__ macro, which is not universally implemented, dangit).
</p></li><li><p>
The message text is made up of zero or more lines, each terminated
by a newline.
</p></li></ol></div><p>Here's some example output:</p><pre class="programlisting">
[1998/08/03 12:55:25, 1] nmbd.c:(659)
Netbios nameserver version 1.9.19-prealpha started.
Copyright Andrew Tridgell 1994-1997
[1998/08/03 12:55:25, 3] loadparm.c:(763)
Initializing global parameters
</pre><p>
Note that in the above example the function names are not listed on
the header line. That's because the example above was generated on an
SGI Indy, and the SGI compiler doesn't support the __FUNCTION__ macro.
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2797071"></a>The DEBUG() Macro</h2></div></div><div></div></div><p>
Use of the DEBUG() macro is unchanged. DEBUG() takes two parameters.
The first is the message level, the second is the body of a function
call to the Debug1() function.
</p><p>That's confusing.</p><p>Here's an example which may help a bit. If you would write</p><pre class="programlisting">
printf( "This is a %s message.\n", "debug" );
</pre><p>
to send the output to stdout, then you would write
</p><pre class="programlisting">
DEBUG( 0, ( "This is a %s message.\n", "debug" ) );
</pre><p>
to send the output to the debug file. All of the normal printf()
formatting escapes work.
</p><p>
Note that in the above example the DEBUG message level is set to 0.
Messages at level 0 always print. Basically, if the message level is
less than or equal to the global value DEBUGLEVEL, then the DEBUG
statement is processed.
</p><p>
The output of the above example would be something like:
</p><pre class="programlisting">
[1998/07/30 16:00:51, 0] file.c:function(128)
This is a debug message.
</pre><p>
Each call to DEBUG() creates a new header *unless* the output produced
by the previous call to DEBUG() did not end with a '\n'. Output to the
debug file is passed through a formatting buffer which is flushed
every time a newline is encountered. If the buffer is not empty when
DEBUG() is called, the new input is simply appended.
</p><p>
...but that's really just a Kludge. It was put in place because
DEBUG() has been used to write partial lines. Here's a simple (dumb)
example of the kind of thing I'm talking about:
</p><pre class="programlisting">
DEBUG( 0, ("The test returned " ) );
if( test() )
DEBUG(0, ("True") );
else
DEBUG(0, ("False") );
DEBUG(0, (".\n") );
</pre><p>
Without the format buffer, the output (assuming test() returned true)
would look like this:
</p><pre class="programlisting">
[1998/07/30 16:00:51, 0] file.c:function(256)
The test returned
[1998/07/30 16:00:51, 0] file.c:function(258)
True
[1998/07/30 16:00:51, 0] file.c:function(261)
.
</pre><p>Which isn't much use. The format buffer kludge fixes this problem.
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2797201"></a>The DEBUGADD() Macro</h2></div></div><div></div></div><p>
In addition to the kludgey solution to the broken line problem
described above, there is a clean solution. The DEBUGADD() macro never
generates a header. It will append new text to the current debug
message even if the format buffer is empty. The syntax of the
DEBUGADD() macro is the same as that of the DEBUG() macro.
</p><pre class="programlisting">
DEBUG( 0, ("This is the first line.\n" ) );
DEBUGADD( 0, ("This is the second line.\nThis is the third line.\n" ) );
</pre><p>Produces</p><pre class="programlisting">
[1998/07/30 16:00:51, 0] file.c:function(512)
This is the first line.
This is the second line.
This is the third line.
</pre></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2797246"></a>The DEBUGLVL() Macro</h2></div></div><div></div></div><p>
One of the problems with the DEBUG() macro was that DEBUG() lines
tended to get a bit long. Consider this example from
nmbd_sendannounce.c:
</p><pre class="programlisting">
DEBUG(3,("send_local_master_announcement: type %x for name %s on subnet %s for workgroup %s\n",
type, global_myname, subrec->subnet_name, work->work_group));
</pre><p>
One solution to this is to break it down using DEBUG() and DEBUGADD(),
as follows:
</p><pre class="programlisting">
DEBUG( 3, ( "send_local_master_announcement: " ) );
DEBUGADD( 3, ( "type %x for name %s ", type, global_myname ) );
DEBUGADD( 3, ( "on subnet %s ", subrec->subnet_name ) );
DEBUGADD( 3, ( "for workgroup %s\n", work->work_group ) );
</pre><p>
A similar, but arguably nicer approach is to use the DEBUGLVL() macro.
This macro returns True if the message level is less than or equal to
the global DEBUGLEVEL value, so:
</p><pre class="programlisting">
if( DEBUGLVL( 3 ) )
{
dbgtext( "send_local_master_announcement: " );
dbgtext( "type %x for name %s ", type, global_myname );
dbgtext( "on subnet %s ", subrec->subnet_name );
dbgtext( "for workgroup %s\n", work->work_group );
}
</pre><p>(The dbgtext() function is explained below.)</p><p>There are a few advantages to this scheme:</p><div class="orderedlist"><ol type="1"><li><p>
The test is performed only once.
</p></li><li><p>
You can allocate variables off of the stack that will only be used
within the DEBUGLVL() block.
</p></li><li><p>
Processing that is only relevant to debug output can be contained
within the DEBUGLVL() block.
</p></li></ol></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2797357"></a>New Functions</h2></div></div><div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2797364"></a>dbgtext()</h3></div></div><div></div></div><p>
This function prints debug message text to the debug file (and
possibly to syslog) via the format buffer. The function uses a
variable argument list just like printf() or Debug1(). The
input is printed into a buffer using the vslprintf() function,
and then passed to format_debug_text().
If you use DEBUGLVL() you will probably print the body of the
message using dbgtext().
</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2797383"></a>dbghdr()</h3></div></div><div></div></div><p>
This is the function that writes a debug message header.
Headers are not processed via the format buffer. Also note that
if the format buffer is not empty, a call to dbghdr() will not
produce any output. See the comments in dbghdr() for more info.
</p><p>
It is not likely that this function will be called directly. It
is used by DEBUG() and DEBUGADD().
</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2797406"></a>format_debug_text()</h3></div></div><div></div></div><p>
This is a static function in debug.c. It stores the output text
for the body of the message in a buffer until it encounters a
newline. When the newline character is found, the buffer is
written to the debug file via the Debug1() function, and the
buffer is reset. This allows us to add the indentation at the
beginning of each line of the message body, and also ensures
that the output is written a line at a time (which cleans up
syslog output).
</p></div></div></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="CodingSuggestions"></a>Chapter 4. Coding Suggestions</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Steve</span> <span class="surname">French</span></h3></div></div><div><div class="author"><h3 class="author"><span class="firstname">Simo</span> <span class="surname">Sorce</span></h3></div></div><div><div class="author"><h3 class="author"><span class="firstname">Andrew</span> <span class="surname">Bartlett</span></h3></div></div><div><div class="author"><h3 class="author"><span class="firstname">Tim</span> <span class="surname">Potter</span></h3></div></div><div><div class="author"><h3 class="author"><span class="firstname">Martin</span> <span class="surname">Pool</span></h3></div></div></div><div></div></div><p>
So you want to add code to Samba ...
</p><p>
One of the daunting tasks facing a programmer attempting to write code for
Samba is understanding the various coding conventions used by those most
active in the project. These conventions were mostly unwritten and helped
improve either the portability, stability or consistency of the code. This
document will attempt to document a few of the more important coding
practices used at this time on the Samba project. The coding practices are
expected to change slightly over time, and even to grow as more is learned
about obscure portability considerations. Two existing documents
<tt class="filename">samba/source/internals.doc</tt> and
<tt class="filename">samba/source/architecture.doc</tt> provide
additional information.
</p><p>
The loosely related question of coding style is very personal and this
document does not attempt to address that subject, except to say that I
have observed that eight character tabs seem to be preferred in Samba
source. If you are interested in the topic of coding style, two oft-quoted
documents are:
</p><p>
<ulink url="http://lxr.linux.no/source/Documentation/CodingStyle">http://lxr.linux.no/source/Documentation/CodingStyle</ulink>
</p><p>
<ulink url="http://www.fsf.org/prep/standards_toc.html">http://www.fsf.org/prep/standards_toc.html</ulink>
</p><p>
But note that coding style in Samba varies due to the many different
programmers who have contributed.
</p><p>
Following are some considerations you should use when adding new code to
Samba. First and foremost remember that:
</p><p>
Portability is a primary consideration in adding function, as is network
compatability with de facto, existing, real world CIFS/SMB implementations.
There are lots of platforms that Samba builds on so use caution when adding
a call to a library function that is not invoked in existing Samba code.
Also note that there are many quite different SMB/CIFS clients that Samba
tries to support, not all of which follow the SNIA CIFS Technical Reference
(or the earlier Microsoft reference documents or the X/Open book on the SMB
Standard) perfectly.
</p><p>
Here are some other suggestions:
</p><div class="orderedlist"><ol type="1"><li><p>
use d_printf instead of printf for display text
reason: enable auto-substitution of translated language text
</p></li><li><p>
use SAFE_FREE instead of free
reason: reduce traps due to null pointers
</p></li><li><p>
don't use bzero use memset, or ZERO_STRUCT and ZERO_STRUCTP macros
reason: not POSIX
</p></li><li><p>
don't use strcpy and strlen (use safe_* equivalents)
reason: to avoid traps due to buffer overruns
</p></li><li><p>
don't use getopt_long, use popt functions instead
reason: portability
</p></li><li><p>
explicitly add const qualifiers on parm passing in functions where parm
is input only (somewhat controversial but const can be #defined away)
</p></li><li><p>
when passing a va_list as an arg, or assigning one to another
please use the VA_COPY() macro
reason: on some platforms, va_list is a struct that must be
initialized in each function...can SEGV if you don't.
</p></li><li><p>
discourage use of threads
reason: portability (also see architecture.doc)
</p></li><li><p>
don't explicitly include new header files in C files - new h files
should be included by adding them once to includes.h
reason: consistency
</p></li><li><p>
don't explicitly extern functions (they are autogenerated by
"make proto" into proto.h)
reason: consistency
</p></li><li><p>
use endian safe macros when unpacking SMBs (see byteorder.h and
internals.doc)
reason: not everyone uses Intel
</p></li><li><p>
Note Unicode implications of charset handling (see internals.doc). See
pull_* and push_* and convert_string functions.
reason: Internationalization
</p></li><li><p>
Don't assume English only
reason: See above
</p></li><li><p>
Try to avoid using in/out parameters (functions that return data which
overwrites input parameters)
reason: Can cause stability problems
</p></li><li><p>
Ensure copyright notices are correct, don't append Tridge's name to code
that he didn't write. If you did not write the code, make sure that it
can coexist with the rest of the Samba GPLed code.
</p></li><li><p>
Consider usage of DATA_BLOBs for length specified byte-data.
reason: stability
</p></li><li><p>
Take advantage of tdbs for database like function
reason: consistency
</p></li><li><p>
Don't access the SAM_ACCOUNT structure directly, they should be accessed
via pdb_get...() and pdb_set...() functions.
reason: stability, consistency
</p></li><li><p>
Don't check a password directly against the passdb, always use the
check_password() interface.
reason: long term pluggability
</p></li><li><p>
Try to use asprintf rather than pstrings and fstrings where possible
</p></li><li><p>
Use normal C comments / * instead of C++ comments // like
this. Although the C++ comment format is part of the C99
standard, some older vendor C compilers do not accept it.
</p></li><li><p>
Try to write documentation for API functions and structures
explaining the point of the code, the way it should be used, and
any special conditions or results. Mark these with a double-star
comment start / ** so that they can be picked up by Doxygen, as in
this file.
</p></li><li><p>
Keep the scope narrow. This means making functions/variables
static whenever possible. We don't want our namespace
polluted. Each module should have a minimal number of externally
visible functions or variables.
</p></li><li><p>
Use function pointers to keep knowledge about particular pieces of
code isolated in one place. We don't want a particular piece of
functionality to be spread out across lots of places - that makes
for fragile, hand to maintain code. Instead, design an interface
and use tables containing function pointers to implement specific
functionality. This is particularly important for command
interpreters.
</p></li><li><p>
Think carefully about what it will be like for someone else to add
to and maintain your code. If it would be hard for someone else to
maintain then do it another way.
</p></li></ol></div><p>
The suggestions above are simply that, suggestions, but the information may
help in reducing the routine rework done on new code. The preceeding list
is expected to change routinely as new support routines and macros are
added.
</p></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="internals"></a>Chapter 5. Samba Internals</h2></div><div><div class="author"><h3 class="author"><span class="firstname">David</span> <span class="surname">Chappell</span></h3><div class="affiliation"><div class="address"><p><tt class="email"><<a href="mailto:David.Chappell@mail.trincoll.edu">David.Chappell@mail.trincoll.edu</a>></tt></p></div></div></div></div><div><p class="pubdate">8 May 1996</p></div></div><div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><a href="#id2799193">Character Handling</a></dt><dt><a href="#id2799218">The new functions</a></dt><dt><a href="#id2852640">Macros in byteorder.h</a></dt><dd><dl><dt><a href="#id2852653">CVAL(buf,pos)</a></dt><dt><a href="#id2852667">PVAL(buf,pos)</a></dt><dt><a href="#id2852680">SCVAL(buf,pos,val)</a></dt><dt><a href="#id2852694">SVAL(buf,pos)</a></dt><dt><a href="#id2852710">IVAL(buf,pos)</a></dt><dt><a href="#id2852724">SVALS(buf,pos)</a></dt><dt><a href="#id2852738">IVALS(buf,pos)</a></dt><dt><a href="#id2852753">SSVAL(buf,pos,val)</a></dt><dt><a href="#id2852767">SIVAL(buf,pos,val)</a></dt><dt><a href="#id2852782">SSVALS(buf,pos,val)</a></dt><dt><a href="#id2852796">SIVALS(buf,pos,val)</a></dt><dt><a href="#id2852810">RSVAL(buf,pos)</a></dt><dt><a href="#id2852825">RIVAL(buf,pos)</a></dt><dt><a href="#id2852839">RSSVAL(buf,pos,val)</a></dt><dt><a href="#id2852851">RSIVAL(buf,pos,val)</a></dt></dl></dd><dt><a href="#id2852867">LAN Manager Samba API</a></dt><dd><dl><dt><a href="#id2852903">Parameters</a></dt><dt><a href="#id2858884">Return value</a></dt></dl></dd><dt><a href="#id2858969">Code character table</a></dt></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2799193"></a>Character Handling</h2></div></div><div></div></div><p>
This section describes character set handling in Samba, as implemented in
Samba 3.0 and above
</p><p>
In the past Samba had very ad-hoc character set handling. Scattered
throughout the code were numerous calls which converted particular
strings to/from DOS codepages. The problem is that there was no way of
telling if a particular char* is in dos codepage or unix
codepage. This led to a nightmare of code that tried to cope with
particular cases without handlingt the general case.
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2799218"></a>The new functions</h2></div></div><div></div></div><p>
The new system works like this:
</p><div class="orderedlist"><ol type="1"><li><p>
all char* strings inside Samba are "unix" strings. These are
multi-byte strings that are in the charset defined by the "unix
charset" option in smb.conf.
</p></li><li><p>
there is no single fixed character set for unix strings, but any
character set that is used does need the following properties:
</p><div class="orderedlist"><ol type="a"><li><p>
must not contain NULLs except for termination
</p></li><li><p>
must be 7-bit compatible with C strings, so that a constant
string or character in C will be byte-for-byte identical to the
equivalent string in the chosen character set.
</p></li><li><p>
when you uppercase or lowercase a string it does not become
longer than the original string
</p></li><li><p>
must be able to correctly hold all characters that your client
will throw at it
</p></li></ol></div><p>
For example, UTF-8 is fine, and most multi-byte asian character sets
are fine, but UCS2 could not be used for unix strings as they
contain nulls.
</p></li><li><p>
when you need to put a string into a buffer that will be sent on the
wire, or you need a string in a character set format that is
compatible with the clients character set then you need to use a
pull_ or push_ function. The pull_ functions pull a string from a
wire buffer into a (multi-byte) unix string. The push_ functions
push a string out to a wire buffer.
</p></li><li><p>
the two main pull_ and push_ functions you need to understand are
pull_string and push_string. These functions take a base pointer
that should point at the start of the SMB packet that the string is
in. The functions will check the flags field in this packet to
automatically determine if the packet is marked as a unicode packet,
and they will choose whether to use unicode for this string based on
that flag. You may also force this decision using the STR_UNICODE or
STR_ASCII flags. For use in smbd/ and libsmb/ there are wrapper
functions clistr_ and srvstr_ that call the pull_/push_ functions
with the appropriate first argument.
</p><p>
You may also call the pull_ascii/pull_ucs2 or push_ascii/push_ucs2
functions if you know that a particular string is ascii or
unicode. There are also a number of other convenience functions in
charcnv.c that call the pull_/push_ functions with particularly
common arguments, such as pull_ascii_pstring()
</p></li><li><p>
The biggest thing to remember is that internal (unix) strings in Samba
may now contain multi-byte characters. This means you cannot assume
that characters are always 1 byte long. Often this means that you will
have to convert strings to ucs2 and back again in order to do some
(seemingly) simple task. For examples of how to do this see functions
like strchr_m(). I know this is very slow, and we will eventually
speed it up but right now we want this stuff correct not fast.
</p></li><li><p>
all lp_ functions now return unix strings. The magic "DOS" flag on
parameters is gone.
</p></li><li><p>
all vfs functions take unix strings. Don't convert when passing to them
</p></li></ol></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2852640"></a>Macros in byteorder.h</h2></div></div><div></div></div><p>
This section describes the macros defined in byteorder.h. These macros
are used extensively in the Samba code.
</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2852653"></a>CVAL(buf,pos)</h3></div></div><div></div></div><p>
returns the byte at offset pos within buffer buf as an unsigned character.
</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2852667"></a>PVAL(buf,pos)</h3></div></div><div></div></div><p>returns the value of CVAL(buf,pos) cast to type unsigned integer.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2852680"></a>SCVAL(buf,pos,val)</h3></div></div><div></div></div><p>sets the byte at offset pos within buffer buf to value val.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2852694"></a>SVAL(buf,pos)</h3></div></div><div></div></div><p>
returns the value of the unsigned short (16 bit) little-endian integer at
offset pos within buffer buf. An integer of this type is sometimes
refered to as "USHORT".
</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2852710"></a>IVAL(buf,pos)</h3></div></div><div></div></div><p>returns the value of the unsigned 32 bit little-endian integer at offset
pos within buffer buf.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2852724"></a>SVALS(buf,pos)</h3></div></div><div></div></div><p>returns the value of the signed short (16 bit) little-endian integer at
offset pos within buffer buf.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2852738"></a>IVALS(buf,pos)</h3></div></div><div></div></div><p>returns the value of the signed 32 bit little-endian integer at offset pos
within buffer buf.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2852753"></a>SSVAL(buf,pos,val)</h3></div></div><div></div></div><p>sets the unsigned short (16 bit) little-endian integer at offset pos within
buffer buf to value val.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2852767"></a>SIVAL(buf,pos,val)</h3></div></div><div></div></div><p>sets the unsigned 32 bit little-endian integer at offset pos within buffer
buf to the value val.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2852782"></a>SSVALS(buf,pos,val)</h3></div></div><div></div></div><p>sets the short (16 bit) signed little-endian integer at offset pos within
buffer buf to the value val.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2852796"></a>SIVALS(buf,pos,val)</h3></div></div><div></div></div><p>sets the signed 32 bit little-endian integer at offset pos withing buffer
buf to the value val.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2852810"></a>RSVAL(buf,pos)</h3></div></div><div></div></div><p>returns the value of the unsigned short (16 bit) big-endian integer at
offset pos within buffer buf.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2852825"></a>RIVAL(buf,pos)</h3></div></div><div></div></div><p>returns the value of the unsigned 32 bit big-endian integer at offset
pos within buffer buf.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2852839"></a>RSSVAL(buf,pos,val)</h3></div></div><div></div></div><p>sets the value of the unsigned short (16 bit) big-endian integer at
offset pos within buffer buf to value val.
refered to as "USHORT".</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2852851"></a>RSIVAL(buf,pos,val)</h3></div></div><div></div></div><p>sets the value of the unsigned 32 bit big-endian integer at offset
pos within buffer buf to value val.</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2852867"></a>LAN Manager Samba API</h2></div></div><div></div></div><p>
This section describes the functions need to make a LAN Manager RPC call.
This information had been obtained by examining the Samba code and the LAN
Manager 2.0 API documentation. It should not be considered entirely
reliable.
</p><p>
</p><pre class="programlisting">
call_api(int prcnt, int drcnt, int mprcnt, int mdrcnt,
char *param, char *data, char **rparam, char **rdata);
</pre><p>
</p><p>
This function is defined in client.c. It uses an SMB transaction to call a
remote api.
</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2852903"></a>Parameters</h3></div></div><div></div></div><p>The parameters are as follows:</p><div class="orderedlist"><ol type="1"><li><p>
prcnt: the number of bytes of parameters begin sent.
</p></li><li><p>
drcnt: the number of bytes of data begin sent.
</p></li><li><p>
mprcnt: the maximum number of bytes of parameters which should be returned
</p></li><li><p>
mdrcnt: the maximum number of bytes of data which should be returned
</p></li><li><p>
param: a pointer to the parameters to be sent.
</p></li><li><p>
data: a pointer to the data to be sent.
</p></li><li><p>
rparam: a pointer to a pointer which will be set to point to the returned
paramters. The caller of call_api() must deallocate this memory.
</p></li><li><p>
rdata: a pointer to a pointer which will be set to point to the returned
data. The caller of call_api() must deallocate this memory.
</p></li></ol></div><p>
These are the parameters which you ought to send, in the order of their
appearance in the parameter block:
</p><div class="orderedlist"><ol type="1"><li><p>
An unsigned 16 bit integer API number. You should set this value with
SSVAL(). I do not know where these numbers are described.
</p></li><li><p>
An ASCIIZ string describing the parameters to the API function as defined
in the LAN Manager documentation. The first parameter, which is the server
name, is ommited. This string is based uppon the API function as described
in the manual, not the data which is actually passed.
</p></li><li><p>
An ASCIIZ string describing the data structure which ought to be returned.
</p></li><li><p>
Any parameters which appear in the function call, as defined in the LAN
Manager API documentation, after the "Server" and up to and including the
"uLevel" parameters.
</p></li><li><p>
An unsigned 16 bit integer which gives the size in bytes of the buffer we
will use to receive the returned array of data structures. Presumably this
should be the same as mdrcnt. This value should be set with SSVAL().
</p></li><li><p>
An ASCIIZ string describing substructures which should be returned. If no
substructures apply, this string is of zero length.
</p></li></ol></div><p>
The code in client.c always calls call_api() with no data. It is unclear
when a non-zero length data buffer would be sent.
</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2858884"></a>Return value</h3></div></div><div></div></div><p>
The returned parameters (pointed to by rparam), in their order of appearance
are:</p><div class="orderedlist"><ol type="1"><li><p>
An unsigned 16 bit integer which contains the API function's return code.
This value should be read with SVAL().
</p></li><li><p>
An adjustment which tells the amount by which pointers in the returned
data should be adjusted. This value should be read with SVAL(). Basically,
the address of the start of the returned data buffer should have the returned
pointer value added to it and then have this value subtracted from it in
order to obtain the currect offset into the returned data buffer.
</p></li><li><p>
A count of the number of elements in the array of structures returned.
It is also possible that this may sometimes be the number of bytes returned.
</p></li></ol></div><p>
When call_api() returns, rparam points to the returned parameters. The
first if these is the result code. It will be zero if the API call
suceeded. This value by be read with "SVAL(rparam,0)".
</p><p>
The second parameter may be read as "SVAL(rparam,2)". It is a 16 bit offset
which indicates what the base address of the returned data buffer was when
it was built on the server. It should be used to correct pointer before
use.
</p><p>
The returned data buffer contains the array of returned data structures.
Note that all pointers must be adjusted before use. The function
fix_char_ptr() in client.c can be used for this purpose.
</p><p>
The third parameter (which may be read as "SVAL(rparam,4)") has something to
do with indicating the amount of data returned or possibly the amount of
data which can be returned if enough buffer space is allowed.
</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2858969"></a>Code character table</h2></div></div><div></div></div><p>
Certain data structures are described by means of ASCIIz strings containing
code characters. These are the code characters:
</p><div class="orderedlist"><ol type="1"><li><p>
W a type byte little-endian unsigned integer
</p></li><li><p>
N a count of substructures which follow
</p></li><li><p>
D a four byte little-endian unsigned integer
</p></li><li><p>
B a byte (with optional count expressed as trailing ASCII digits)
</p></li><li><p>
z a four byte offset to a NULL terminated string
</p></li><li><p>
l a four byte offset to non-string user data
</p></li><li><p>
b an offset to data (with count expressed as trailing ASCII digits)
</p></li><li><p>
r pointer to returned data buffer???
</p></li><li><p>
L length in bytes of returned data buffer???
</p></li><li><p>
h number of bytes of information available???
</p></li></ol></div></div></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="parsing"></a>Chapter 6. The smb.conf file</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Chris</span> <span class="surname">Hertel</span></h3></div></div><div><p class="pubdate">November 1997</p></div></div><div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><a href="#id2859088">Lexical Analysis</a></dt><dd><dl><dt><a href="#id2859179">Handling of Whitespace</a></dt><dt><a href="#id2859235">Handling of Line Continuation</a></dt><dt><a href="#id2859300">Line Continuation Quirks</a></dt></dl></dd><dt><a href="#id2859396">Syntax</a></dt><dd><dl><dt><a href="#id2858239">About params.c</a></dt></dl></dd></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2859088"></a>Lexical Analysis</h2></div></div><div></div></div><p>
Basically, the file is processed on a line by line basis. There are
four types of lines that are recognized by the lexical analyzer
(params.c):
</p><div class="orderedlist"><ol type="1"><li><p>
Blank lines - Lines containing only whitespace.
</p></li><li><p>
Comment lines - Lines beginning with either a semi-colon or a
pound sign (';' or '#').
</p></li><li><p>
Section header lines - Lines beginning with an open square bracket ('[').
</p></li><li><p>
Parameter lines - Lines beginning with any other character.
(The default line type.)
</p></li></ol></div><p>
The first two are handled exclusively by the lexical analyzer, which
ignores them. The latter two line types are scanned for
</p><div class="orderedlist"><ol type="1"><li><p>
- Section names
</p></li><li><p>
- Parameter names
</p></li><li><p>
- Parameter values
</p></li></ol></div><p>
These are the only tokens passed to the parameter loader
(loadparm.c). Parameter names and values are divided from one
another by an equal sign: '='.
</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2859179"></a>Handling of Whitespace</h3></div></div><div></div></div><p>
Whitespace is defined as all characters recognized by the isspace()
function (see ctype(3C)) except for the newline character ('\n')
The newline is excluded because it identifies the end of the line.
</p><div class="orderedlist"><ol type="1"><li><p>
The lexical analyzer scans past white space at the beginning of a line.
</p></li><li><p>
Section and parameter names may contain internal white space. All
whitespace within a name is compressed to a single space character.
</p></li><li><p>
Internal whitespace within a parameter value is kept verbatim with
the exception of carriage return characters ('\r'), all of which
are removed.
</p></li><li><p>
Leading and trailing whitespace is removed from names and values.
</p></li></ol></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2859235"></a>Handling of Line Continuation</h3></div></div><div></div></div><p>
Long section header and parameter lines may be extended across
multiple lines by use of the backslash character ('\\'). Line
continuation is ignored for blank and comment lines.
</p><p>
If the last (non-whitespace) character within a section header or on
a parameter line is a backslash, then the next line will be
(logically) concatonated with the current line by the lexical
analyzer. For example:
</p><pre class="programlisting">
param name = parameter value string \
with line continuation.
</pre><p>Would be read as</p><pre class="programlisting">
param name = parameter value string with line continuation.
</pre><p>
Note that there are five spaces following the word 'string',
representing the one space between 'string' and '\\' in the top
line, plus the four preceeding the word 'with' in the second line.
(Yes, I'm counting the indentation.)
</p><p>
Line continuation characters are ignored on blank lines and at the end
of comments. They are *only* recognized within section and parameter
lines.
</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2859300"></a>Line Continuation Quirks</h3></div></div><div></div></div><p>Note the following example:</p><pre class="programlisting">
param name = parameter value string \
\
with line continuation.
</pre><p>
The middle line is *not* parsed as a blank line because it is first
concatonated with the top line. The result is
</p><pre class="programlisting">
param name = parameter value string with line continuation.
</pre><p>The same is true for comment lines.</p><pre class="programlisting">
param name = parameter value string \
; comment \
with a comment.
</pre><p>This becomes:</p><pre class="programlisting">
param name = parameter value string ; comment with a comment.
</pre><p>
On a section header line, the closing bracket (']') is considered a
terminating character, and the rest of the line is ignored. The lines
</p><pre class="programlisting">
[ section name ] garbage \
param name = value
</pre><p>are read as</p><pre class="programlisting">
[section name]
param name = value
</pre></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2859396"></a>Syntax</h2></div></div><div></div></div><p>The syntax of the smb.conf file is as follows:</p><pre class="programlisting">
<file> :== { <section> } EOF
<section> :== <section header> { <parameter line> }
<section header> :== '[' NAME ']'
<parameter line> :== NAME '=' VALUE NL
</pre><p>Basically, this means that</p><div class="orderedlist"><ol type="1"><li><p>
a file is made up of zero or more sections, and is terminated by
an EOF (we knew that).
</p></li><li><p>
A section is made up of a section header followed by zero or more
parameter lines.
</p></li><li><p>
A section header is identified by an opening bracket and
terminated by the closing bracket. The enclosed NAME identifies
the section.
</p></li><li><p>
A parameter line is divided into a NAME and a VALUE. The *first*
equal sign on the line separates the NAME from the VALUE. The
VALUE is terminated by a newline character (NL = '\n').
</p></li></ol></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2858239"></a>About params.c</h3></div></div><div></div></div><p>
The parsing of the config file is a bit unusual if you are used to
lex, yacc, bison, etc. Both lexical analysis (scanning) and parsing
are performed by params.c. Values are loaded via callbacks to
loadparm.c.
</p></div></div></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="unix-smb"></a>Chapter 7. NetBIOS in a Unix World</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Andrew</span> <span class="surname">Tridgell</span></h3></div></div><div><p class="pubdate">April 1995</p></div></div><div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><a href="#id2858286">Introduction</a></dt><dt><a href="#id2858311">Usernames</a></dt><dt><a href="#id2858381">File Ownership</a></dt><dt><a href="#id2858418">Passwords</a></dt><dt><a href="#id2858463">Locking</a></dt><dt><a href="#id2858525">Deny Modes</a></dt><dt><a href="#id2858555">Trapdoor UIDs</a></dt><dt><a href="#id2858580">Port numbers</a></dt><dt><a href="#id2858634">Protocol Complexity</a></dt></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2858286"></a>Introduction</h2></div></div><div></div></div><p>
This is a short document that describes some of the issues that
confront a SMB implementation on unix, and how Samba copes with
them. They may help people who are looking at unix<->PC
interoperability.
</p><p>
It was written to help out a person who was writing a paper on unix to
PC connectivity.
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2858311"></a>Usernames</h2></div></div><div></div></div><p>
The SMB protocol has only a loose username concept. Early SMB
protocols (such as CORE and COREPLUS) have no username concept at
all. Even in later protocols clients often attempt operations
(particularly printer operations) without first validating a username
on the server.
</p><p>
Unix security is based around username/password pairs. A unix box
should not allow clients to do any substantive operation without some
sort of validation.
</p><p>
The problem mostly manifests itself when the unix server is in "share
level" security mode. This is the default mode as the alternative
"user level" security mode usually forces a client to connect to the
server as the same user for each connected share, which is
inconvenient in many sites.
</p><p>
In "share level" security the client normally gives a username in the
"session setup" protocol, but does not supply an accompanying
password. The client then connects to resources using the "tree
connect" protocol, and supplies a password. The problem is that the
user on the PC types the username and the password in different
contexts, unaware that they need to go together to give access to the
server. The username is normally the one the user typed in when they
"logged onto" the PC (this assumes Windows for Workgroups). The
password is the one they chose when connecting to the disk or printer.
</p><p>
The user often chooses a totally different username for their login as
for the drive connection. Often they also want to access different
drives as different usernames. The unix server needs some way of
divining the correct username to combine with each password.
</p><p>
Samba tries to avoid this problem using several methods. These succeed
in the vast majority of cases. The methods include username maps, the
service%user syntax, the saving of session setup usernames for later
validation and the derivation of the username from the service name
(either directly or via the user= option).
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2858381"></a>File Ownership</h2></div></div><div></div></div><p>
The commonly used SMB protocols have no way of saying "you can't do
that because you don't own the file". They have, in fact, no concept
of file ownership at all.
</p><p>
This brings up all sorts of interesting problems. For example, when
you copy a file to a unix drive, and the file is world writeable but
owned by another user the file will transfer correctly but will
receive the wrong date. This is because the utime() call under unix
only succeeds for the owner of the file, or root, even if the file is
world writeable. For security reasons Samba does all file operations
as the validated user, not root, so the utime() fails. This can stuff
up shared development diectories as programs like "make" will not get
file time comparisons right.
</p><p>
There are several possible solutions to this problem, including
username mapping, and forcing a specific username for particular
shares.
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2858418"></a>Passwords</h2></div></div><div></div></div><p>
Many SMB clients uppercase passwords before sending them. I have no
idea why they do this. Interestingly WfWg uppercases the password only
if the server is running a protocol greater than COREPLUS, so
obviously it isn't just the data entry routines that are to blame.
</p><p>
Unix passwords are case sensitive. So if users use mixed case
passwords they are in trouble.
</p><p>
Samba can try to cope with this by either using the "password level"
option which causes Samba to try the offered password with up to the
specified number of case changes, or by using the "password server"
option which allows Samba to do its validation via another machine
(typically a WinNT server).
</p><p>
Samba supports the password encryption method used by SMB
clients. Note that the use of password encryption in Microsoft
networking leads to password hashes that are "plain text equivalent".
This means that it is *VERY* important to ensure that the Samba
smbpasswd file containing these password hashes is only readable
by the root user. See the documentation ENCRYPTION.txt for more
details.
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2858463"></a>Locking</h2></div></div><div></div></div><p>
Since samba 2.2, samba supports other types of locking as well. This
section is outdated.
</p><p>
The locking calls available under a DOS/Windows environment are much
richer than those available in unix. This means a unix server (like
Samba) choosing to use the standard fcntl() based unix locking calls
to implement SMB locking has to improvise a bit.
</p><p>
One major problem is that dos locks can be in a 32 bit (unsigned)
range. Unix locking calls are 32 bits, but are signed, giving only a 31
bit range. Unfortunately OLE2 clients use the top bit to select a
locking range used for OLE semaphores.
</p><p>
To work around this problem Samba compresses the 32 bit range into 31
bits by appropriate bit shifting. This seems to work but is not
ideal. In a future version a separate SMB lockd may be added to cope
with the problem.
</p><p>
It also doesn't help that many unix lockd daemons are very buggy and
crash at the slightest provocation. They normally go mostly unused in
a unix environment because few unix programs use byte range
locking. The stress of huge numbers of lock requests from dos/windows
clients can kill the daemon on some systems.
</p><p>
The second major problem is the "opportunistic locking" requested by
some clients. If a client requests opportunistic locking then it is
asking the server to notify it if anyone else tries to do something on
the same file, at which time the client will say if it is willing to
give up its lock. Unix has no simple way of implementing
opportunistic locking, and currently Samba has no support for it.
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2858525"></a>Deny Modes</h2></div></div><div></div></div><p>
When a SMB client opens a file it asks for a particular "deny mode" to
be placed on the file. These modes (DENY_NONE, DENY_READ, DENY_WRITE,
DENY_ALL, DENY_FCB and DENY_DOS) specify what actions should be
allowed by anyone else who tries to use the file at the same time. If
DENY_READ is placed on the file, for example, then any attempt to open
the file for reading should fail.
</p><p>
Unix has no equivalent notion. To implement this Samba uses either lock
files based on the files inode and placed in a separate lock
directory or a shared memory implementation. The lock file method
is clumsy and consumes processing and file resources,
the shared memory implementation is vastly prefered and is turned on
by default for those systems that support it.
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2858555"></a>Trapdoor UIDs</h2></div></div><div></div></div><p>
A SMB session can run with several uids on the one socket. This
happens when a user connects to two shares with different
usernames. To cope with this the unix server needs to switch uids
within the one process. On some unixes (such as SCO) this is not
possible. This means that on those unixes the client is restricted to
a single uid.
</p><p>
Note that you can also get the "trapdoor uid" message for other
reasons. Please see the FAQ for details.
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2858580"></a>Port numbers</h2></div></div><div></div></div><p>
There is a convention that clients on sockets use high "unprivilaged"
port numbers (>1000) and connect to servers on low "privilaged" port
numbers. This is enforced in Unix as non-root users can't open a
socket for listening on port numbers less than 1000.
</p><p>
Most PC based SMB clients (such as WfWg and WinNT) don't follow this
convention completely. The main culprit is the netbios nameserving on
udp port 137. Name query requests come from a source port of 137. This
is a problem when you combine it with the common firewalling technique
of not allowing incoming packets on low port numbers. This means that
these clients can't query a netbios nameserver on the other side of a
low port based firewall.
</p><p>
The problem is more severe with netbios node status queries. I've
found that WfWg, Win95 and WinNT3.5 all respond to netbios node status
queries on port 137 no matter what the source port was in the
request. This works between machines that are both using port 137, but
it means it's not possible for a unix user to do a node status request
to any of these OSes unless they are running as root. The answer comes
back, but it goes to port 137 which the unix user can't listen
on. Interestingly WinNT3.1 got this right - it sends node status
responses back to the source port in the request.
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2858634"></a>Protocol Complexity</h2></div></div><div></div></div><p>
There are many "protocol levels" in the SMB protocol. It seems that
each time new functionality was added to a Microsoft operating system,
they added the equivalent functions in a new protocol level of the SMB
protocol to "externalise" the new capabilities.
</p><p>
This means the protocol is very "rich", offering many ways of doing
each file operation. This means SMB servers need to be complex and
large. It also means it is very difficult to make them bug free. It is
not just Samba that suffers from this problem, other servers such as
WinNT don't support every variation of every call and it has almost
certainly been a headache for MS developers to support the myriad of
SMB calls that are available.
</p><p>
There are about 65 "top level" operations in the SMB protocol (things
like SMBread and SMBwrite). Some of these include hundreds of
sub-functions (SMBtrans has at least 120 sub-functions, like
DosPrintQAdd and NetSessionEnum). All of them take several options
that can change the way they work. Many take dozens of possible
"information levels" that change the structures that need to be
returned. Samba supports all but 2 of the "top level" functions. It
supports only 8 (so far) of the SMBtrans sub-functions. Even NT
doesn't support them all.
</p><p>
Samba currently supports up to the "NT LM 0.12" protocol, which is the
one preferred by Win95 and WinNT3.5. Luckily this protocol level has a
"capabilities" field which specifies which super-duper new-fangled
options the server suports. This helps to make the implementation of
this protocol level much easier.
</p><p>
There is also a problem with the SMB specications. SMB is a X/Open
spec, but the X/Open book is far from ideal, and fails to cover many
important issues, leaving much to the imagination. Microsoft recently
renamed the SMB protocol CIFS (Common Internet File System) and have
published new specifications. These are far superior to the old
X/Open documents but there are still undocumented calls and features.
This specification is actively being worked on by a CIFS developers
mailing list hosted by Microsft.
</p></div></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="tracing"></a>Chapter 8. Tracing samba system calls</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Andrew</span> <span class="surname">Tridgell</span></h3><div class="affiliation"><span class="orgname">Samba Team<br></span></div></div></div></div><div></div></div><p>
This file describes how to do a system call trace on Samba to work out
what its doing wrong. This is not for the faint of heart, but if you
are reading this then you are probably desperate.
</p><p>
Actually its not as bad as the the above makes it sound, just don't
expect the output to be very pretty :-)
</p><p>
Ok, down to business. One of the big advantages of unix systems is
that they nearly all come with a system trace utility that allows you
to monitor all system calls that a program is making. This is
extremely using for debugging and also helps when trying to work out
why something is slower than you expect. You can use system tracing
without any special compilation options.
</p><p>
The system trace utility is called different things on different
systems. On Linux systems its called strace. Under SunOS 4 its called
trace. Under SVR4 style systems (including solaris) its called
truss. Under many BSD systems its called ktrace.
</p><p>
The first thing you should do is read the man page for your native
system call tracer. In the discussion below I'll assume its called
strace as strace is the only portable system tracer (its available for
free for many unix types) and its also got some of the nicest
features.
</p><p>
Next, try using strace on some simple commands. For example, <b class="command">strace
ls</b> or <b class="command">strace echo hello</b>.
</p><p>
You'll notice that it produces a LOT of output. It is showing you the
arguments to every system call that the program makes and the
result. Very little happens in a program without a system call so you
get lots of output. You'll also find that it produces a lot of
"preamble" stuff showing the loading of shared libraries etc. Ignore
this (unless its going wrong!)
</p><p>
For example, the only line that really matters in the <b class="command">strace echo
hello</b> output is:
</p><pre class="programlisting">
write(1, "hello\n", 6) = 6
</pre><p>all the rest is just setting up to run the program.</p><p>
Ok, now you're familiar with strace. To use it on Samba you need to
strace the running smbd daemon. The way I tend ot use it is to first
login from my Windows PC to the Samba server, then use smbstatus to
find which process ID that client is attached to, then as root I do
<b class="command">strace -p PID</b> to attach to that process. I normally redirect the
stderr output from this command to a file for later perusal. For
example, if I'm using a csh style shell:
</p><p><b class="command">strace -f -p 3872 >& strace.out</b></p><p>or with a sh style shell:</p><p><b class="command">strace -f -p 3872 > strace.out 2>&1</b></p><p>
Note the "-f" option. This is only available on some systems, and
allows you to trace not just the current process, but any children it
forks. This is great for finding printing problems caused by the
"print command" being wrong.
</p><p>
Once you are attached you then can do whatever it is on the client
that is causing problems and you will capture all the system calls
that smbd makes.
</p><p>
So how do you interpret the results? Generally I search through the
output for strings that I know will appear when the problem
happens. For example, if I am having touble with permissions on a file
I would search for that files name in the strace output and look at
the surrounding lines. Another trick is to match up file descriptor
numbers and "follow" what happens to an open file until it is closed.
</p><p>
Beyond this you will have to use your initiative. To give you an idea
of what you are looking for here is a piece of strace output that
shows that <tt class="filename">/dev/null</tt> is not world writeable, which
causes printing to fail with Samba:
</p><pre class="programlisting">
[pid 28268] open("/dev/null", O_RDWR) = -1 EACCES (Permission denied)
[pid 28268] open("/dev/null", O_WRONLY) = -1 EACCES (Permission denied)
</pre><p>
The process is trying to first open <tt class="filename">/dev/null</tt> read-write
then read-only. Both fail. This means <tt class="filename">/dev/null</tt> has
incorrect permissions.
</p></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="windows-debug"></a>Chapter 9. Finding useful information on windows</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Jelmer</span> <span class="othername">R.</span> <span class="surname">Vernooij</span></h3><div class="affiliation"><span class="orgname">The Samba Team<br></span><div class="address"><p><tt class="email"><<a href="mailto:jelmer@samba.org">jelmer@samba.org</a>></tt></p></div></div></div></div><div><div class="author"><h3 class="author"><span class="firstname">Andrew</span> <span class="surname">Tridgell</span></h3><div class="affiliation"><span class="orgname">Samba Team<br></span><div class="address"><p><tt class="email"><<a href="mailto:tridge@samba.org">tridge@samba.org</a>></tt></p></div></div></div></div></div><div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><a href="#id2869073">Netlogon debugging output</a></dt></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2869073"></a>Netlogon debugging output</h2></div></div><div></div></div><div class="procedure"><ol type="1"><li><p>stop netlogon service on PDC</p></li><li><p>rename original netlogon.dll to netlogon.dll.original</p></li><li><p>copy checked version of netlogon.dll to system32 directory</p></li><li><p>set HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters\DBFlag to 0x20000004</p></li><li><p>start netlogon service on PDC</p></li></ol></div></div></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="ntdomain"></a>Chapter 10. NT Domain RPC's</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Luke</span> <span class="surname">Leighton</span></h3><div class="affiliation"><div class="address"><p><tt class="email"><<a href="mailto:lkcl@switchboard.net">lkcl@switchboard.net</a>></tt></p></div></div></div></div><div><div class="author"><h3 class="author"><span class="firstname">Paul</span> <span class="surname">Ashton</span></h3><div class="affiliation"><div class="address"><p><tt class="email"><<a href="mailto:paul@argo.demon.co.uk">paul@argo.demon.co.uk</a>></tt></p></div></div></div></div><div><div class="author"><h3 class="author"><span class="firstname">Duncan</span> <span class="surname">Stansfield</span></h3><div class="affiliation"><div class="address"><p><tt class="email"><<a href="mailto:duncans@sco.com">duncans@sco.com</a>></tt></p></div></div></div></div><div><p class="pubdate">01 November 97(version 0.0.24)</p></div></div><div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><a href="#id2869214">Introduction</a></dt><dd><dl><dt><a href="#id2869414">Sources</a></dt><dt><a href="#id2869450">Credits</a></dt></dl></dd><dt><a href="#id2869488">Notes and Structures</a></dt><dd><dl><dt><a href="#id2869495">Notes</a></dt><dt><a href="#id2869570">Enumerations</a></dt><dt><a href="#id2869784">Structures</a></dt></dl></dd><dt><a href="#id2872733">MSRPC over Transact Named Pipe</a></dt><dd><dl><dt><a href="#id2872746">MSRPC Pipes</a></dt><dt><a href="#id2872849">Header</a></dt><dt><a href="#id2873718">Tail</a></dt><dt><a href="#id2873764">RPC Bind / Bind Ack</a></dt><dt><a href="#id2873945">NTLSA Transact Named Pipe</a></dt><dt><a href="#id2874109">LSA Open Policy</a></dt><dt><a href="#id2874235">LSA Query Info Policy</a></dt><dt><a href="#id2874342">LSA Enumerate Trusted Domains</a></dt><dt><a href="#id2874433">LSA Open Secret</a></dt><dt><a href="#id2874543">LSA Close</a></dt><dt><a href="#id2874608">LSA Lookup SIDS</a></dt><dt><a href="#id2874818">LSA Lookup Names</a></dt></dl></dd><dt><a href="#id2867818">NETLOGON rpc Transact Named Pipe</a></dt><dd><dl><dt><a href="#id2867980">LSA Request Challenge</a></dt><dt><a href="#id2868114">LSA Authenticate 2</a></dt><dt><a href="#id2868261">LSA Server Password Set</a></dt><dt><a href="#id2868376">LSA SAM Logon</a></dt><dt><a href="#id2868479">LSA SAM Logoff</a></dt></dl></dd><dt><a href="#id2868571">\\MAILSLOT\NET\NTLOGON</a></dt><dd><dl><dt><a href="#id2868583">Query for PDC</a></dt><dt><a href="#id2868850">SAM Logon</a></dt></dl></dd><dt><a href="#id2877631">SRVSVC Transact Named Pipe</a></dt><dd><dl><dt><a href="#id2877676">Net Share Enum</a></dt><dt><a href="#id2877896">Net Server Get Info</a></dt></dl></dd><dt><a href="#id2878012">Cryptographic side of NT Domain Authentication</a></dt><dd><dl><dt><a href="#id2878020">Definitions</a></dt><dt><a href="#id2878182">Protocol</a></dt><dt><a href="#id2878280">Comments</a></dt></dl></dd><dt><a href="#id2878330">SIDs and RIDs</a></dt><dd><dl><dt><a href="#id2878368">Well-known SIDs</a></dt><dt><a href="#id2878683">Well-known RIDS</a></dt></dl></dd></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2869214"></a>Introduction</h2></div></div><div></div></div><p>
This document contains information to provide an NT workstation with login
services, without the need for an NT server. It is the sgml version of <ulink url="http://mailhost.cb1.com/~lkcl/cifsntdomain.txt">http://mailhost.cb1.com/~lkcl/cifsntdomain.txt</ulink>, controlled by Luke.
</p><p>
It should be possible to select a domain instead of a workgroup (in the NT
workstation's TCP/IP settings) and after the obligatory reboot, type in a
username, password, select a domain and successfully log in. I would
appreciate any feedback on your experiences with this process, and any
comments, corrections and additions to this document.
</p><p>
The packets described here can be easily derived from (and are probably
better understood using) Netmon.exe. You will need to use the version
of Netmon that matches your system, in order to correctly decode the
NETLOGON, lsarpc and srvsvc Transact pipes. This document is derived from
NT Service Pack 1 and its corresponding version of Netmon. It is intended
that an annotated packet trace be produced, which will likely be more
instructive than this document.
</p><p>
Also needed, to fully implement NT Domain Login Services, is the
document describing the cryptographic part of the NT authentication.
This document is available from comp.protocols.smb; from the ntsecurity.net
digest and from the samba digest, amongst other sources.
</p><p>
A copy is available from:
</p><p><ulink url="http://ntbugtraq.rc.on.ca/SCRIPTS/WA.EXE?A2=ind9708;L=ntbugtraq;O=A;P=2935">http://ntbugtraq.rc.on.ca/SCRIPTS/WA.EXE?A2=ind9708;L=ntbugtraq;O=A;P=2935</ulink></p><p><ulink url="http://mailhost.cb1.com/~lkcl/crypt.html">http://mailhost.cb1.com/~lkcl/crypt.html</ulink></p><p>
A c-code implementation, provided by <ulink url="mailto:linus@incolumitas.se">Linus Nordberg</ulink>
of this protocol is available from:
</p><p><ulink url="http://samba.org/cgi-bin/mfs/01/digest/1997/97aug/0391.html">http://samba.org/cgi-bin/mfs/01/digest/1997/97aug/0391.html</ulink></p><p><ulink url="http://mailhost.cb1.com/~lkcl/crypt.txt">http://mailhost.cb1.com/~lkcl/crypt.txt</ulink></p><p>
Also used to provide debugging information is the Check Build version of
NT workstation, and enabling full debugging in NETLOGON. This is
achieved by setting the following REG_SZ registry key to 0x1ffffff:
</p><p><tt class="filename">HKLM\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters</tt></p><p><span class="emphasis"><em>Incorrect direct editing of the registry can cause your
machine to fail. Then again, so can incorrect implementation of this
protocol. See "Liability:" above.</em></span></p><p>
Bear in mind that each packet over-the-wire will have its origin in an
API call. Therefore, there are likely to be structures, enumerations
and defines that are usefully documented elsewhere.
</p><p>
This document is by no means complete or authoritative. Missing sections
include, but are not limited to:
</p><div class="orderedlist"><ol type="1"><li><p>Mappings of RIDs to usernames (and vice-versa).</p></li><li><p>What a User ID is and what a Group ID is.</p></li><li><p>The exact meaning/definition of various magic constants or enumerations.</p></li><li><p>The reply error code and use of that error code when a
workstation becomes a member of a domain (to be described later).
Failure to return this error code will make the workstation report
that it is already a member of the domain.</p></li><li><p>the cryptographic side of the NetrServerPasswordSet command,
which would allow the workstation to change its password. This password is
used to generate the long-term session key. [It is possible to reject this
command, and keep the default workstation password].</p></li></ol></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2869414"></a>Sources</h3></div></div><div></div></div><table class="simplelist" border="0" summary="Simple list"><tr><td>cket Traces from Netmonitor (Service Pack 1 and above)</td></tr><tr><td>ul Ashton and Luke Leighton's other "NT Domain" doc.</td></tr><tr><td>FS documentation - cifs6.txt</td></tr><tr><td>FS documentation - cifsrap2.txt</td></tr></table></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2869450"></a>Credits</h3></div></div><div></div></div><table class="simplelist" border="0" summary="Simple list"><tr><td>Paul Ashton: loads of work with Net Monitor; understanding the NT authentication system; reference implementation of the NT domain support on which this document is originally based.</td></tr><tr><td>Duncan Stansfield: low-level analysis of MSRPC Pipes.</td></tr><tr><td>Linus Nordberg: producing c-code from Paul's crypto spec.</td></tr><tr><td>Windows Sourcer development team</td></tr></table></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2869488"></a>Notes and Structures</h2></div></div><div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2869495"></a>Notes</h3></div></div><div></div></div><div class="orderedlist"><ol type="1"><li><p>
In the SMB Transact pipes, some "Structures", described here, appear to be
4-byte aligned with the SMB header, at their start. Exactly which
"Structures" need aligning is not precisely known or documented.
</p></li><li><p>
In the UDP NTLOGON Mailslots, some "Structures", described here, appear to be
2-byte aligned with the start of the mailslot, at their start.
</p></li><li><p>
Domain SID is of the format S-revision-version-auth1-auth2...authN.
e.g S-1-5-123-456-789-123-456. the 5 could be a sub-revision.
</p></li><li><p>
any undocumented buffer pointers must be non-zero if the string buffer it
refers to contains characters. exactly what value they should be is unknown.
0x0000 0002 seems to do the trick to indicate that the buffer exists. a
NULL buffer pointer indicates that the string buffer is of zero length.
If the buffer pointer is NULL, then it is suspected that the structure it
refers to is NOT put into (or taken out of) the SMB data stream. This is
empirically derived from, for example, the LSA SAM Logon response packet,
where if the buffer pointer is NULL, the user information is not inserted
into the data stream. Exactly what happens with an array of buffer pointers
is not known, although an educated guess can be made.
</p></li><li><p>
an array of structures (a container) appears to have a count and a pointer.
if the count is zero, the pointer is also zero. no further data is put
into or taken out of the SMB data stream. if the count is non-zero, then
the pointer is also non-zero. immediately following the pointer is the
count again, followed by an array of container sub-structures. the count
appears a third time after the last sub-structure.
</p></li></ol></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2869570"></a>Enumerations</h3></div></div><div></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2869578"></a>MSRPC Header type</h4></div></div><div></div></div><p>command number in the msrpc packet header</p><div class="variablelist"><dl><dt><span class="term">MSRPC_Request:</span></dt><dd><p>0x00</p></dd><dt><span class="term">MSRPC_Response:</span></dt><dd><p>0x02</p></dd><dt><span class="term">MSRPC_Bind:</span></dt><dd><p>0x0B</p></dd><dt><span class="term">MSRPC_BindAck:</span></dt><dd><p>0x0C</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2869653"></a>MSRPC Packet info</h4></div></div><div></div></div><p>The meaning of these flags is undocumented</p><div class="variablelist"><dl><dt><span class="term">FirstFrag:</span></dt><dd><p>0x01 </p></dd><dt><span class="term">LastFrag:</span></dt><dd><p>0x02 </p></dd><dt><span class="term">NotaFrag:</span></dt><dd><p>0x04 </p></dd><dt><span class="term">RecRespond:</span></dt><dd><p>0x08 </p></dd><dt><span class="term">NoMultiplex:</span></dt><dd><p>0x10 </p></dd><dt><span class="term">NotForIdemp:</span></dt><dd><p>0x20 </p></dd><dt><span class="term">NotforBcast:</span></dt><dd><p>0x40 </p></dd><dt><span class="term">NoUuid:</span></dt><dd><p>0x80 </p></dd></dl></div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2869784"></a>Structures</h3></div></div><div></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2869791"></a>VOID *</h4></div></div><div></div></div><p>sizeof VOID* is 32 bits.</p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2869802"></a>char</h4></div></div><div></div></div><p>sizeof char is 8 bits.</p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2869814"></a>UTIME</h4></div></div><div></div></div><p>UTIME is 32 bits, indicating time in seconds since 01jan1970. documented in cifs6.txt (section 3.5 page, page 30).</p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2869827"></a>NTTIME</h4></div></div><div></div></div><p>NTTIME is 64 bits. documented in cifs6.txt (section 3.5 page, page 30).</p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2869839"></a>DOM_SID (domain SID structure)</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UINT32</span></dt><dd><p>num of sub-authorities in domain SID</p></dd><dt><span class="term">UINT8</span></dt><dd><p>SID revision number</p></dd><dt><span class="term">UINT8</span></dt><dd><p>num of sub-authorities in domain SID</p></dd><dt><span class="term">UINT8[6]</span></dt><dd><p>6 bytes for domain SID - Identifier Authority.</p></dd><dt><span class="term">UINT16[n_subauths]</span></dt><dd><p>domain SID sub-authorities</p></dd></dl></div><p><span class="emphasis"><em>Note: the domain SID is documented elsewhere.</em></span>
</p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2869932"></a>STR (string)</h4></div></div><div></div></div><p>STR (string) is a char[] : a null-terminated string of ascii characters.</p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2869946"></a>UNIHDR (unicode string header) </h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UINT16</span></dt><dd><p>length of unicode string</p></dd><dt><span class="term">UINT16</span></dt><dd><p>max length of unicode string</p></dd><dt><span class="term">UINT32</span></dt><dd><p>4 - undocumented.</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2870002"></a>UNIHDR2 (unicode string header plus buffer pointer)</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UNIHDR</span></dt><dd><p>unicode string header</p></dd><dt><span class="term">VOID*</span></dt><dd><p>undocumented buffer pointer</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2870044"></a>UNISTR (unicode string)</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UINT16[]</span></dt><dd><p>null-terminated string of unicode characters.</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2870072"></a>NAME (length-indicated unicode string)</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UINT32</span></dt><dd><p>length of unicode string</p></dd><dt><span class="term">UINT16[]</span></dt><dd><p>null-terminated string of unicode characters.</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2870114"></a>UNISTR2 (aligned unicode string)</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UINT8[]</span></dt><dd><p>padding to get unicode string 4-byte aligned with the start of the SMB header.</p></dd><dt><span class="term">UINT32</span></dt><dd><p>max length of unicode string</p></dd><dt><span class="term">UINT32</span></dt><dd><p>0 - undocumented</p></dd><dt><span class="term">UINT32</span></dt><dd><p>length of unicode string</p></dd><dt><span class="term">UINT16[]</span></dt><dd><p>string of uncode characters</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2870200"></a>OBJ_ATTR (object attributes)</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UINT32</span></dt><dd><p>0x18 - length (in bytes) including the length field.</p></dd><dt><span class="term">VOID*</span></dt><dd><p>0 - root directory (pointer)</p></dd><dt><span class="term">VOID*</span></dt><dd><p>0 - object name (pointer)</p></dd><dt><span class="term">UINT32</span></dt><dd><p>0 - attributes (undocumented)</p></dd><dt><span class="term">VOID*</span></dt><dd><p>0 - security descriptior (pointer)</p></dd><dt><span class="term">UINT32</span></dt><dd><p>0 - security quality of service</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2870293"></a>POL_HND (LSA policy handle)</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">char[20]</span></dt><dd><p>policy handle</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2870320"></a>DOM_SID2 (domain SID structure, SIDS stored in unicode)</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UINT32</span></dt><dd><p>5 - SID type</p></dd><dt><span class="term">UINT32</span></dt><dd><p>0 - undocumented</p></dd><dt><span class="term">UNIHDR2</span></dt><dd><p>domain SID unicode string header</p></dd><dt><span class="term">UNISTR</span></dt><dd><p>domain SID unicode string</p></dd></dl></div><p><span class="emphasis"><em>Note: there is a conflict between the unicode string header and the unicode string itself as to which to use to indicate string length. this will need to be resolved.</em></span></p><p><span class="emphasis"><em>Note: the SID type indicates, for example, an alias; a well-known group etc. this is documented somewhere.</em></span></p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2870407"></a>DOM_RID (domain RID structure)</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UINT32</span></dt><dd><p>5 - well-known SID. 1 - user SID (see ShowACLs)</p></dd><dt><span class="term">UINT32</span></dt><dd><p>5 - undocumented</p></dd><dt><span class="term">UINT32</span></dt><dd><p>domain RID </p></dd><dt><span class="term">UINT32</span></dt><dd><p>0 - domain index out of above reference domains</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2870476"></a>LOG_INFO (server, account, client structure)</h4></div></div><div></div></div><p><span class="emphasis"><em>Note: logon server name starts with two '\' characters and is upper case.</em></span></p><p><span class="emphasis"><em>Note: account name is the logon client name from the LSA Request Challenge, with a $ on the end of it, in upper case.</em></span></p><div class="variablelist"><dl><dt><span class="term">VOID*</span></dt><dd><p>undocumented buffer pointer</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>logon server unicode string</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>account name unicode string</p></dd><dt><span class="term">UINT16</span></dt><dd><p>sec_chan - security channel type</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>logon client machine unicode string</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2870576"></a>CLNT_SRV (server, client names structure)</h4></div></div><div></div></div><p><span class="emphasis"><em>Note: logon server name starts with two '\' characters and is upper case.</em></span></p><div class="variablelist"><dl><dt><span class="term">VOID*</span></dt><dd><p>undocumented buffer pointer</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>logon server unicode string</p></dd><dt><span class="term">VOID*</span></dt><dd><p>undocumented buffer pointer</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>logon client machine unicode string</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2870653"></a>CREDS (credentials + time stamp)</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">char[8]</span></dt><dd><p>credentials</p></dd><dt><span class="term">UTIME</span></dt><dd><p>time stamp</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2870694"></a>CLNT_INFO2 (server, client structure, client credentials)</h4></div></div><div></div></div><p><span class="emphasis"><em>Note: whenever this structure appears in a request, you must take a copy of the client-calculated credentials received, because they will beused in subsequent credential checks. the presumed intention is to
maintain an authenticated request/response trail.</em></span></p><div class="variablelist"><dl><dt><span class="term">CLNT_SRV</span></dt><dd><p>client and server names</p></dd><dt><span class="term">UINT8[]</span></dt><dd><p>???? padding, for 4-byte alignment with SMB header.</p></dd><dt><span class="term">VOID*</span></dt><dd><p>pointer to client credentials.</p></dd><dt><span class="term">CREDS</span></dt><dd><p>client-calculated credentials + client time</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2870776"></a>CLNT_INFO (server, account, client structure, client credentials)</h4></div></div><div></div></div><p><span class="emphasis"><em>Note: whenever this structure appears in a request, you must take a copy of the client-calculated credentials received, because they will be used in subsequent credential checks. the presumed intention is to maintain an authenticated request/response trail.</em></span></p><div class="variablelist"><dl><dt><span class="term">LOG_INFO</span></dt><dd><p>logon account info</p></dd><dt><span class="term">CREDS</span></dt><dd><p>client-calculated credentials + client time</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2870829"></a>ID_INFO_1 (id info structure, auth level 1)</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">VOID*</span></dt><dd><p>ptr_id_info_1</p></dd><dt><span class="term">UNIHDR</span></dt><dd><p>domain name unicode header</p></dd><dt><span class="term">UINT32</span></dt><dd><p>param control</p></dd><dt><span class="term">UINT64</span></dt><dd><p>logon ID</p></dd><dt><span class="term">UNIHDR</span></dt><dd><p>user name unicode header</p></dd><dt><span class="term">UNIHDR</span></dt><dd><p>workgroup name unicode header</p></dd><dt><span class="term">char[16]</span></dt><dd><p>arc4 LM OWF Password</p></dd><dt><span class="term">char[16]</span></dt><dd><p>arc4 NT OWF Password</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>domain name unicode string</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>user name unicode string</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>workstation name unicode string</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2871000"></a>SAM_INFO (sam logon/logoff id info structure)</h4></div></div><div></div></div><p><span class="emphasis"><em>Note: presumably, the return credentials is supposedly for the server to verify that the credential chain hasn't been compromised.</em></span></p><div class="variablelist"><dl><dt><span class="term">CLNT_INFO2</span></dt><dd><p>client identification/authentication info</p></dd><dt><span class="term">VOID*</span></dt><dd><p>pointer to return credentials.</p></dd><dt><span class="term">CRED</span></dt><dd><p>return credentials - ignored.</p></dd><dt><span class="term">UINT16</span></dt><dd><p>logon level</p></dd><dt><span class="term">UINT16</span></dt><dd><p>switch value</p></dd></dl></div><pre class="programlisting">
switch (switch_value)
case 1:
{
ID_INFO_1 id_info_1;
}
</pre></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2871104"></a>GID (group id info)</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UINT32</span></dt><dd><p>group id</p></dd><dt><span class="term">UINT32</span></dt><dd><p>user attributes (only used by NT 3.1 and 3.51)</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2871142"></a>DOM_REF (domain reference info)</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">VOID*</span></dt><dd><p>undocumented buffer pointer.</p></dd><dt><span class="term">UINT32</span></dt><dd><p>num referenced domains?</p></dd><dt><span class="term">VOID*</span></dt><dd><p>undocumented domain name buffer pointer.</p></dd><dt><span class="term">UINT32</span></dt><dd><p>32 - max number of entries</p></dd><dt><span class="term">UINT32</span></dt><dd><p>4 - num referenced domains?</p></dd><dt><span class="term">UNIHDR2</span></dt><dd><p>domain name unicode string header</p></dd><dt><span class="term">UNIHDR2[num_ref_doms-1]</span></dt><dd><p>referenced domain unicode string headers</p></dd><dt><span class="term">UNISTR</span></dt><dd><p>domain name unicode string</p></dd><dt><span class="term">DOM_SID[num_ref_doms]</span></dt><dd><p>referenced domain SIDs</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2871285"></a>DOM_INFO (domain info, levels 3 and 5 are the same))</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UINT8[]</span></dt><dd><p>??? padding to get 4-byte alignment with start of SMB header</p></dd><dt><span class="term">UINT16</span></dt><dd><p>domain name string length * 2</p></dd><dt><span class="term">UINT16</span></dt><dd><p>domain name string length * 2</p></dd><dt><span class="term">VOID*</span></dt><dd><p>undocumented domain name string buffer pointer</p></dd><dt><span class="term">VOID*</span></dt><dd><p>undocumented domain SID string buffer pointer</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>domain name (unicode string)</p></dd><dt><span class="term">DOM_SID</span></dt><dd><p>domain SID</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2871398"></a>USER_INFO (user logon info)</h4></div></div><div></div></div><p><span class="emphasis"><em>Note: it would be nice to know what the 16 byte user session key is for.</em></span></p><div class="variablelist"><dl><dt><span class="term">NTTIME</span></dt><dd><p>logon time</p></dd><dt><span class="term">NTTIME</span></dt><dd><p>logoff time</p></dd><dt><span class="term">NTTIME</span></dt><dd><p>kickoff time</p></dd><dt><span class="term">NTTIME</span></dt><dd><p>password last set time</p></dd><dt><span class="term">NTTIME</span></dt><dd><p>password can change time</p></dd><dt><span class="term">NTTIME</span></dt><dd><p>password must change time</p></dd><dt><span class="term">UNIHDR</span></dt><dd><p>username unicode string header</p></dd><dt><span class="term">UNIHDR</span></dt><dd><p>user's full name unicode string header</p></dd><dt><span class="term">UNIHDR</span></dt><dd><p>logon script unicode string header</p></dd><dt><span class="term">UNIHDR</span></dt><dd><p>profile path unicode string header</p></dd><dt><span class="term">UNIHDR</span></dt><dd><p>home directory unicode string header</p></dd><dt><span class="term">UNIHDR</span></dt><dd><p>home directory drive unicode string header</p></dd><dt><span class="term">UINT16</span></dt><dd><p>logon count</p></dd><dt><span class="term">UINT16</span></dt><dd><p>bad password count</p></dd><dt><span class="term">UINT32</span></dt><dd><p>User ID</p></dd><dt><span class="term">UINT32</span></dt><dd><p>Group ID</p></dd><dt><span class="term">UINT32</span></dt><dd><p>num groups</p></dd><dt><span class="term">VOID*</span></dt><dd><p>undocumented buffer pointer to groups.</p></dd><dt><span class="term">UINT32</span></dt><dd><p>user flags</p></dd><dt><span class="term">char[16]</span></dt><dd><p>user session key</p></dd><dt><span class="term">UNIHDR</span></dt><dd><p>logon server unicode string header</p></dd><dt><span class="term">UNIHDR</span></dt><dd><p>logon domain unicode string header</p></dd><dt><span class="term">VOID*</span></dt><dd><p>undocumented logon domain id pointer</p></dd><dt><span class="term">char[40]</span></dt><dd><p>40 undocumented padding bytes. future expansion?</p></dd><dt><span class="term">UINT32</span></dt><dd><p>0 - num_other_sids?</p></dd><dt><span class="term">VOID*</span></dt><dd><p>NULL - undocumented pointer to other domain SIDs.</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>username unicode string</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>user's full name unicode string</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>logon script unicode string</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>profile path unicode string</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>home directory unicode string</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>home directory drive unicode string</p></dd><dt><span class="term">UINT32</span></dt><dd><p>num groups</p></dd><dt><span class="term">GID[num_groups]</span></dt><dd><p>group info</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>logon server unicode string</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>logon domain unicode string</p></dd><dt><span class="term">DOM_SID</span></dt><dd><p>domain SID</p></dd><dt><span class="term">DOM_SID[num_sids]</span></dt><dd><p>other domain SIDs?</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2871961"></a>SH_INFO_1_PTR (pointers to level 1 share info strings)</h4></div></div><div></div></div><p><span class="emphasis"><em>Note: see cifsrap2.txt section5, page 10.</em></span></p><table class="simplelist" border="0" summary="Simple list"><tr><td>0 for shi1_type indicates a Disk.</td></tr><tr><td>1 for shi1_type indicates a Print Queue.</td></tr><tr><td>2 for shi1_type indicates a Device.</td></tr><tr><td>3 for shi1_type indicates an IPC pipe.</td></tr><tr><td>0x8000 0000 (top bit set in shi1_type) indicates a hidden share.</td></tr></table><div class="variablelist"><dl><dt><span class="term">VOID*</span></dt><dd><p>shi1_netname - pointer to net name</p></dd><dt><span class="term">UINT32</span></dt><dd><p>shi1_type - type of share. 0 - undocumented.</p></dd><dt><span class="term">VOID*</span></dt><dd><p>shi1_remark - pointer to comment.</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2872056"></a>SH_INFO_1_STR (level 1 share info strings)</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UNISTR2</span></dt><dd><p>shi1_netname - unicode string of net name</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>shi1_remark - unicode string of comment.</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2872098"></a>SHARE_INFO_1_CTR</h4></div></div><div></div></div><p>share container with 0 entries:</p><div class="variablelist"><dl><dt><span class="term">UINT32</span></dt><dd><p>0 - EntriesRead</p></dd><dt><span class="term">UINT32</span></dt><dd><p>0 - Buffer</p></dd></dl></div><p>share container with > 0 entries:</p><div class="variablelist"><dl><dt><span class="term">UINT32</span></dt><dd><p>EntriesRead</p></dd><dt><span class="term">UINT32</span></dt><dd><p>non-zero - Buffer</p></dd><dt><span class="term">UINT32</span></dt><dd><p>EntriesRead</p></dd><dt><span class="term">SH_INFO_1_PTR[EntriesRead]</span></dt><dd><p>share entry pointers</p></dd><dt><span class="term">SH_INFO_1_STR[EntriesRead]</span></dt><dd><p>share entry strings</p></dd><dt><span class="term">UINT8[]</span></dt><dd><p>padding to get unicode string 4-byte aligned with start of the SMB header.</p></dd><dt><span class="term">UINT32</span></dt><dd><p>EntriesRead</p></dd><dt><span class="term">UINT32</span></dt><dd><p>0 - padding</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2872267"></a>SERVER_INFO_101</h4></div></div><div></div></div><p><span class="emphasis"><em>Note: see cifs6.txt section 6.4 - the fields described therein will be of assistance here. for example, the type listed below is the same as fServerType, which is described in 6.4.1. </em></span></p><div class="variablelist"><dl><dt><span class="term">SV_TYPE_WORKSTATION</span></dt><dd><p>0x00000001 All workstations</p></dd><dt><span class="term">SV_TYPE_SERVER</span></dt><dd><p>0x00000002 All servers</p></dd><dt><span class="term">SV_TYPE_SQLSERVER</span></dt><dd><p>0x00000004 Any server running with SQL server</p></dd><dt><span class="term">SV_TYPE_DOMAIN_CTRL</span></dt><dd><p>0x00000008 Primary domain controller</p></dd><dt><span class="term">SV_TYPE_DOMAIN_BAKCTRL</span></dt><dd><p>0x00000010 Backup domain controller</p></dd><dt><span class="term">SV_TYPE_TIME_SOURCE</span></dt><dd><p>0x00000020 Server running the timesource service</p></dd><dt><span class="term">SV_TYPE_AFP</span></dt><dd><p>0x00000040 Apple File Protocol servers</p></dd><dt><span class="term">SV_TYPE_NOVELL</span></dt><dd><p>0x00000080 Novell servers</p></dd><dt><span class="term">SV_TYPE_DOMAIN_MEMBER</span></dt><dd><p>0x00000100 Domain Member</p></dd><dt><span class="term">SV_TYPE_PRINTQ_SERVER</span></dt><dd><p>0x00000200 Server sharing print queue</p></dd><dt><span class="term">SV_TYPE_DIALIN_SERVER</span></dt><dd><p>0x00000400 Server running dialin service.</p></dd><dt><span class="term">SV_TYPE_XENIX_SERVER</span></dt><dd><p>0x00000800 Xenix server</p></dd><dt><span class="term">SV_TYPE_NT</span></dt><dd><p>0x00001000 NT server</p></dd><dt><span class="term">SV_TYPE_WFW</span></dt><dd><p>0x00002000 Server running Windows for </p></dd><dt><span class="term">SV_TYPE_SERVER_NT</span></dt><dd><p>0x00008000 Windows NT non DC server</p></dd><dt><span class="term">SV_TYPE_POTENTIAL_BROWSER</span></dt><dd><p>0x00010000 Server that can run the browser service</p></dd><dt><span class="term">SV_TYPE_BACKUP_BROWSER</span></dt><dd><p>0x00020000 Backup browser server</p></dd><dt><span class="term">SV_TYPE_MASTER_BROWSER</span></dt><dd><p>0x00040000 Master browser server</p></dd><dt><span class="term">SV_TYPE_DOMAIN_MASTER</span></dt><dd><p>0x00080000 Domain Master Browser server</p></dd><dt><span class="term">SV_TYPE_LOCAL_LIST_ONLY</span></dt><dd><p>0x40000000 Enumerate only entries marked "local"</p></dd><dt><span class="term">SV_TYPE_DOMAIN_ENUM</span></dt><dd><p>0x80000000 Enumerate Domains. The pszServer and pszDomain parameters must be NULL.</p></dd></dl></div><div class="variablelist"><dl><dt><span class="term">UINT32</span></dt><dd><p>500 - platform_id</p></dd><dt><span class="term">VOID*</span></dt><dd><p>pointer to name</p></dd><dt><span class="term">UINT32</span></dt><dd><p>5 - major version</p></dd><dt><span class="term">UINT32</span></dt><dd><p>4 - minor version</p></dd><dt><span class="term">UINT32</span></dt><dd><p>type (SV_TYPE_... bit field)</p></dd><dt><span class="term">VOID*</span></dt><dd><p>pointer to comment</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>sv101_name - unicode string of server name</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>sv_101_comment - unicode string of server comment.</p></dd><dt><span class="term">UINT8[]</span></dt><dd><p>padding to get unicode string 4-byte aligned with start of the SMB header.</p></dd></dl></div></div></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2872733"></a>MSRPC over Transact Named Pipe</h2></div></div><div></div></div><p>For details on the SMB Transact Named Pipe, see cifs6.txt</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2872746"></a>MSRPC Pipes</h3></div></div><div></div></div><p>
The MSRPC is conducted over an SMB Transact Pipe with a name of
<tt class="filename">\PIPE\</tt>. You must first obtain a 16 bit file handle, by
sending a SMBopenX with the pipe name <tt class="filename">\PIPE\srvsvc</tt> for
example. You can then perform an SMB Trans,
and must carry out an SMBclose on the file handle once you are finished.
</p><p>
Trans Requests must be sent with two setup UINT16s, no UINT16 params (none
known about), and UINT8 data parameters sufficient to contain the MSRPC
header, and MSRPC data. The first UINT16 setup parameter must be either
0x0026 to indicate an RPC, or 0x0001 to indicate Set Named Pipe Handle
state. The second UINT16 parameter must be the file handle for the pipe,
obtained above.
</p><p>
The Data section for an API Command of 0x0026 (RPC pipe) in the Trans
Request is the RPC Header, followed by the RPC Data. The Data section for
an API Command of 0x0001 (Set Named Pipe Handle state) is two bytes. The
only value seen for these two bytes is 0x00 0x43.
</p><p>
MSRPC Responses are sent as response data inside standard SMB Trans
responses, with the MSRPC Header, MSRPC Data and MSRPC tail.
</p><p>
It is suspected that the Trans Requests will need to be at least 2-byte
aligned (probably 4-byte). This is standard practice for SMBs. It is also
independent of the observed 4-byte alignments with the start of the MSRPC
header, including the 4-byte alignment between the MSRPC header and the
MSRPC data.
</p><p>
First, an SMBtconX connection is made to the IPC$ share. The connection
must be made using encrypted passwords, not clear-text. Then, an SMBopenX
is made on the pipe. Then, a Set Named Pipe Handle State must be sent,
after which the pipe is ready to accept API commands. Lastly, and SMBclose
is sent.
</p><p>
To be resolved:
</p><p>
lkcl/01nov97 there appear to be two additional bytes after the null-terminated \PIPE\ name for the RPC pipe. Values seen so far are
listed below:</p><pre class="programlisting">
initial SMBopenX request: RPC API command 0x26 params:
"\\PIPE\\lsarpc" 0x65 0x63; 0x72 0x70; 0x44 0x65;
"\\PIPE\\srvsvc" 0x73 0x76; 0x4E 0x00; 0x5C 0x43;
</pre></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2872849"></a>Header</h3></div></div><div></div></div><p>[section to be rewritten, following receipt of work by Duncan Stansfield]</p><p>Interesting note: if you set packed data representation to 0x0100 0000
then all 4-byte and 2-byte word ordering is turned around!</p><p>The start of each of the NTLSA and NETLOGON named pipes begins with:</p><div class="segmentedlist"><p><b>offset: </b>00</p><p><b>Variable type: </b>UINT8</p><p><b>Variable data: </b>5 - RPC major version</p><p><b>offset: </b>01</p><p><b>Variable type: </b>UINT8</p><p><b>Variable data: </b>0 - RPC minor version</p><p><b>offset: </b>02</p><p><b>Variable type: </b>UINT8</p><p><b>Variable data: </b>2 - RPC response packet</p><p><b>offset: </b>03</p><p><b>Variable type: </b>UINT8</p><p><b>Variable data: </b>3 - (FirstFrag bit-wise or with LastFrag)</p><p><b>offset: </b>04</p><p><b>Variable type: </b>UINT32</p><p><b>Variable data: </b>0x1000 0000 - packed data representation</p><p><b>offset: </b>08</p><p><b>Variable type: </b>UINT16</p><p><b>Variable data: </b>fragment length - data size (bytes) inc header and tail.</p><p><b>offset: </b>0A</p><p><b>Variable type: </b>UINT16</p><p><b>Variable data: </b>0 - authentication length </p><p><b>offset: </b>0C</p><p><b>Variable type: </b>UINT32</p><p><b>Variable data: </b>call identifier. matches 12th UINT32 of incoming RPC data.</p><p><b>offset: </b>10</p><p><b>Variable type: </b>UINT32</p><p><b>Variable data: </b>allocation hint - data size (bytes) minus header and tail.</p><p><b>offset: </b>14</p><p><b>Variable type: </b>UINT16</p><p><b>Variable data: </b>0 - presentation context identifier</p><p><b>offset: </b>16</p><p><b>Variable type: </b>UINT8</p><p><b>Variable data: </b>0 - cancel count</p><p><b>offset: </b>17</p><p><b>Variable type: </b>UINT8</p><p><b>Variable data: </b>in replies: 0 - reserved; in requests: opnum - see #defines.</p><p><b>offset: </b>18</p><p><b>Variable type: </b>......</p><p><b>Variable data: </b>start of data (goes on for allocation_hint bytes)</p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2873037"></a>RPC_Packet for request, response, bind and bind acknowledgement</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UINT8 versionmaj</span></dt><dd><p>reply same as request (0x05)</p></dd><dt><span class="term">UINT8 versionmin</span></dt><dd><p>reply same as request (0x00)</p></dd><dt><span class="term">UINT8 type</span></dt><dd><p>one of the MSRPC_Type enums</p></dd><dt><span class="term">UINT8 flags</span></dt><dd><p>reply same as request (0x00 for Bind, 0x03 for Request)</p></dd><dt><span class="term">UINT32 representation</span></dt><dd><p>reply same as request (0x00000010)</p></dd><dt><span class="term">UINT16 fraglength</span></dt><dd><p>the length of the data section of the SMB trans packet</p></dd><dt><span class="term">UINT16 authlength</span></dt><dd><p></p></dd><dt><span class="term">UINT32 callid</span></dt><dd><p>call identifier. (e.g. 0x00149594)</p></dd><dt><span class="term">* stub USE TvPacket</span></dt><dd><p>the remainder of the packet depending on the "type"</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2873171"></a>Interface identification</h4></div></div><div></div></div><p>the interfaces are numbered. as yet I haven't seen more than one interface used on the same pipe name srvsvc</p><pre class="programlisting">
abstract (0x4B324FC8, 0x01D31670, 0x475A7812, 0x88E16EBF, 0x00000003)
transfer (0x8A885D04, 0x11C91CEB, 0x0008E89F, 0x6048102B, 0x00000002)
</pre></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2873198"></a>RPC_Iface RW</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UINT8 byte[16]</span></dt><dd><p>16 bytes of number</p></dd><dt><span class="term">UINT32 version</span></dt><dd><p>the interface number</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2873236"></a>RPC_ReqBind RW</h4></div></div><div></div></div><p>the remainder of the packet after the header if "type" was Bind in the response header, "type" should be BindAck</p><div class="variablelist"><dl><dt><span class="term">UINT16 maxtsize</span></dt><dd><p>maximum transmission fragment size (0x1630)</p></dd><dt><span class="term">UINT16 maxrsize</span></dt><dd><p>max receive fragment size (0x1630)</p></dd><dt><span class="term">UINT32 assocgid</span></dt><dd><p>associated group id (0x0)</p></dd><dt><span class="term">UINT32 numelements</span></dt><dd><p>the number of elements (0x1)</p></dd><dt><span class="term">UINT16 contextid</span></dt><dd><p>presentation context identifier (0x0)</p></dd><dt><span class="term">UINT8 numsyntaxes</span></dt><dd><p>the number of syntaxes (has always been 1?)(0x1)</p></dd><dt><span class="term">UINT8[]</span></dt><dd><p>4-byte alignment padding, against SMB header</p></dd><dt><span class="term">* abstractint USE RPC_Iface</span></dt><dd><p>num and vers. of interface client is using</p></dd><dt><span class="term">* transferint USE RPC_Iface</span></dt><dd><p>num and vers. of interface to use for replies</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2873376"></a>RPC_Address RW</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UINT16 length</span></dt><dd><p>length of the string including null terminator</p></dd><dt><span class="term">* port USE string</span></dt><dd><p>the string above in single byte, null terminated form</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2873416"></a>RPC_ResBind RW</h4></div></div><div></div></div><p>the response to place after the header in the reply packet</p><div class="variablelist"><dl><dt><span class="term">UINT16 maxtsize</span></dt><dd><p>same as request</p></dd><dt><span class="term">UINT16 maxrsize</span></dt><dd><p>same as request</p></dd><dt><span class="term">UINT32 assocgid</span></dt><dd><p>zero</p></dd><dt><span class="term">* secondaddr USE RPC_Address</span></dt><dd><p>the address string, as described earlier</p></dd><dt><span class="term">UINT8[]</span></dt><dd><p>4-byte alignment padding, against SMB header</p></dd><dt><span class="term">UINT8 numresults</span></dt><dd><p>the number of results (0x01)</p></dd><dt><span class="term">UINT8[]</span></dt><dd><p>4-byte alignment padding, against SMB header</p></dd><dt><span class="term">UINT16 result</span></dt><dd><p>result (0x00 = accept)</p></dd><dt><span class="term">UINT16 reason</span></dt><dd><p>reason (0x00 = no reason specified)</p></dd><dt><span class="term">* transfersyntax USE RPC_Iface</span></dt><dd><p>the transfer syntax from the request</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2873566"></a>RPC_ReqNorm RW</h4></div></div><div></div></div><p>the remainder of the packet after the header for every other other request</p><div class="variablelist"><dl><dt><span class="term">UINT32 allochint</span></dt><dd><p>the size of the stub data in bytes</p></dd><dt><span class="term">UINT16 prescontext</span></dt><dd><p>presentation context identifier (0x0)</p></dd><dt><span class="term">UINT16 opnum</span></dt><dd><p>operation number (0x15)</p></dd><dt><span class="term">* stub USE TvPacket</span></dt><dd><p>a packet dependent on the pipe name (probably the interface) and the op number)</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2873638"></a>RPC_ResNorm RW</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UINT32 allochint</span></dt><dd><p># size of the stub data in bytes</p></dd><dt><span class="term">UINT16 prescontext</span></dt><dd><p># presentation context identifier (same as request)</p></dd><dt><span class="term">UINT8 cancelcount</span></dt><dd><p># cancel count? (0x0)</p></dd><dt><span class="term">UINT8 reserved</span></dt><dd><p># 0 - one byte padding</p></dd><dt><span class="term">* stub USE TvPacket</span></dt><dd><p># the remainder of the reply</p></dd></dl></div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2873718"></a>Tail</h3></div></div><div></div></div><p>The end of each of the NTLSA and NETLOGON named pipes ends with:</p><div class="variablelist"><dl><dt><span class="term">......</span></dt><dd><p>end of data</p></dd><dt><span class="term">UINT32</span></dt><dd><p>return code</p></dd></dl></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2873764"></a>RPC Bind / Bind Ack</h3></div></div><div></div></div><p>
RPC Binds are the process of associating an RPC pipe (e.g \PIPE\lsarpc)
with a "transfer syntax" (see RPC_Iface structure). The purpose for doing
this is unknown.
</p><p><span class="emphasis"><em>Note: The RPC_ResBind SMB Transact request is sent with two uint16 setup parameters. The first is 0x0026; the second is the file handle
returned by the SMBopenX Transact response.</em></span></p><p><span class="emphasis"><em>Note: The RPC_ResBind members maxtsize, maxrsize and assocgid are the same in the response as the same members in the RPC_ReqBind. The
RPC_ResBind member transfersyntax is the same in the response as
the</em></span></p><p><span class="emphasis"><em>Note: The RPC_ResBind response member secondaddr contains the name of what is presumed to be the service behind the RPC pipe. The
mapping identified so far is:</em></span></p><div class="variablelist"><dl><dt><span class="term">initial SMBopenX request:</span></dt><dd><p>RPC_ResBind response:</p></dd><dt><span class="term">"\\PIPE\\srvsvc"</span></dt><dd><p>"\\PIPE\\ntsvcs"</p></dd><dt><span class="term">"\\PIPE\\samr"</span></dt><dd><p>"\\PIPE\\lsass"</p></dd><dt><span class="term">"\\PIPE\\lsarpc"</span></dt><dd><p>"\\PIPE\\lsass"</p></dd><dt><span class="term">"\\PIPE\\wkssvc"</span></dt><dd><p>"\\PIPE\\wksvcs"</p></dd><dt><span class="term">"\\PIPE\\NETLOGON"</span></dt><dd><p>"\\PIPE\\NETLOGON"</p></dd></dl></div><p><span class="emphasis"><em>Note: The RPC_Packet fraglength member in both the Bind Request and Bind Acknowledgment must contain the length of the entire RPC data, including the RPC_Packet header.</em></span></p><p>Request:</p><table class="simplelist" border="0" summary="Simple list"><tr><td>RPC_Packet</td></tr><tr><td>RPC_ReqBind</td></tr></table><p>Response:</p><table class="simplelist" border="0" summary="Simple list"><tr><td>RPC_Packet</td></tr><tr><td>RPC_ResBind</td></tr></table></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2873945"></a>NTLSA Transact Named Pipe</h3></div></div><div></div></div><p>The sequence of actions taken on this pipe are:</p><table class="simplelist" border="0" summary="Simple list"><tr><td>Establish a connection to the IPC$ share (SMBtconX). use encrypted passwords.</td></tr><tr><td>Open an RPC Pipe with the name "\\PIPE\\lsarpc". Store the file handle.</td></tr><tr><td>Using the file handle, send a Set Named Pipe Handle state to 0x4300.</td></tr><tr><td>Send an LSA Open Policy request. Store the Policy Handle.</td></tr><tr><td>Using the Policy Handle, send LSA Query Info Policy requests, etc.</td></tr><tr><td>Using the Policy Handle, send an LSA Close.</td></tr><tr><td>Close the IPC$ share.</td></tr></table><p>Defines for this pipe, identifying the query are:</p><div class="variablelist"><dl><dt><span class="term">LSA Open Policy:</span></dt><dd><p>0x2c</p></dd><dt><span class="term">LSA Query Info Policy:</span></dt><dd><p>0x07</p></dd><dt><span class="term">LSA Enumerate Trusted Domains:</span></dt><dd><p>0x0d</p></dd><dt><span class="term">LSA Open Secret:</span></dt><dd><p>0xff</p></dd><dt><span class="term">LSA Lookup SIDs:</span></dt><dd><p>0xfe</p></dd><dt><span class="term">LSA Lookup Names:</span></dt><dd><p>0xfd</p></dd><dt><span class="term">LSA Close:</span></dt><dd><p>0x00</p></dd></dl></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2874109"></a>LSA Open Policy</h3></div></div><div></div></div><p><span class="emphasis"><em>Note: The policy handle can be anything you like.</em></span></p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2874122"></a>Request</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">VOID*</span></dt><dd><p>buffer pointer</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>server name - unicode string starting with two '\'s</p></dd><dt><span class="term">OBJ_ATTR</span></dt><dd><p>object attributes</p></dd><dt><span class="term">UINT32</span></dt><dd><p>1 - desired access</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2874193"></a>Response</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">POL_HND</span></dt><dd><p>LSA policy handle</p></dd><dt><span class="term">return</span></dt><dd><p>0 - indicates success</p></dd></dl></div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2874235"></a>LSA Query Info Policy</h3></div></div><div></div></div><p><span class="emphasis"><em>Note: The info class in response must be the same as that in the request.</em></span></p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2874249"></a>Request</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">POL_HND</span></dt><dd><p>LSA policy handle</p></dd><dt><span class="term">UINT16</span></dt><dd><p>info class (also a policy handle?)</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2874288"></a>Response</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">VOID*</span></dt><dd><p>undocumented buffer pointer</p></dd><dt><span class="term">UINT16</span></dt><dd><p>info class (same as info class in request).</p></dd></dl></div><pre class="programlisting">
switch (info class)
case 3:
case 5:
{
DOM_INFO domain info, levels 3 and 5 (are the same).
}
return 0 - indicates success
</pre></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2874342"></a>LSA Enumerate Trusted Domains</h3></div></div><div></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2874350"></a>Request</h4></div></div><div></div></div><p>no extra data</p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2874362"></a>Response</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UINT32</span></dt><dd><p>0 - enumeration context</p></dd><dt><span class="term">UINT32</span></dt><dd><p>0 - entries read</p></dd><dt><span class="term">UINT32</span></dt><dd><p>0 - trust information</p></dd><dt><span class="term">return</span></dt><dd><p>0x8000 001a - "no trusted domains" success code</p></dd></dl></div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2874433"></a>LSA Open Secret</h3></div></div><div></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2874440"></a>Request</h4></div></div><div></div></div><p>no extra data</p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2874452"></a>Response</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UINT32</span></dt><dd><p>0 - undocumented</p></dd><dt><span class="term">UINT32</span></dt><dd><p>0 - undocumented</p></dd><dt><span class="term">UINT32</span></dt><dd><p>0 - undocumented</p></dd><dt><span class="term">UINT32</span></dt><dd><p>0 - undocumented</p></dd><dt><span class="term">UINT32</span></dt><dd><p>0 - undocumented</p></dd></dl></div><p>return 0x0C00 0034 - "no such secret" success code</p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2874543"></a>LSA Close</h3></div></div><div></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2874550"></a>Request</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">POL_HND</span></dt><dd><p>policy handle to be closed</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2874577"></a>Response</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">POL_HND</span></dt><dd><p>0s - closed policy handle (all zeros)</p></dd></dl></div><p>return 0 - indicates success</p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2874608"></a>LSA Lookup SIDS</h3></div></div><div></div></div><p><span class="emphasis"><em>Note: num_entries in response must be same as num_entries in request.</em></span></p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2874621"></a>Request</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">POL_HND</span></dt><dd><p>LSA policy handle</p></dd><dt><span class="term">UINT32</span></dt><dd><p>num_entries</p></dd><dt><span class="term">VOID*</span></dt><dd><p>undocumented domain SID buffer pointer</p></dd><dt><span class="term">VOID*</span></dt><dd><p>undocumented domain name buffer pointer</p></dd><dt><span class="term">VOID*[num_entries] undocumented domain SID pointers to be looked up.
</span></dt><dd><p>DOM_SID[num_entries] domain SIDs to be looked up.</p></dd><dt><span class="term">char[16]</span></dt><dd><p>completely undocumented 16 bytes.</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2874721"></a>Response</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">DOM_REF</span></dt><dd><p>domain reference response</p></dd><dt><span class="term">UINT32</span></dt><dd><p>num_entries (listed above)</p></dd><dt><span class="term">VOID*</span></dt><dd><p>undocumented buffer pointer</p></dd><dt><span class="term">UINT32</span></dt><dd><p>num_entries (listed above)</p></dd><dt><span class="term">DOM_SID2[num_entries]</span></dt><dd><p>domain SIDs (from Request, listed above).</p></dd><dt><span class="term">UINT32</span></dt><dd><p>num_entries (listed above)</p></dd></dl></div><p>return 0 - indicates success</p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2874818"></a>LSA Lookup Names</h3></div></div><div></div></div><p><span class="emphasis"><em>Note: num_entries in response must be same as num_entries in request.</em></span></p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2874831"></a>Request</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">POL_HND</span></dt><dd><p>LSA policy handle</p></dd><dt><span class="term">UINT32</span></dt><dd><p>num_entries</p></dd><dt><span class="term">UINT32</span></dt><dd><p>num_entries</p></dd><dt><span class="term">VOID*</span></dt><dd><p>undocumented domain SID buffer pointer</p></dd><dt><span class="term">VOID*</span></dt><dd><p>undocumented domain name buffer pointer</p></dd><dt><span class="term">NAME[num_entries]</span></dt><dd><p>names to be looked up.</p></dd><dt><span class="term">char[]</span></dt><dd><p>undocumented bytes - falsely translated SID structure?</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2867720"></a>Response</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">DOM_REF</span></dt><dd><p>domain reference response</p></dd><dt><span class="term">UINT32</span></dt><dd><p>num_entries (listed above)</p></dd><dt><span class="term">VOID*</span></dt><dd><p>undocumented buffer pointer</p></dd><dt><span class="term">UINT32</span></dt><dd><p>num_entries (listed above)</p></dd><dt><span class="term">DOM_RID[num_entries]</span></dt><dd><p>domain SIDs (from Request, listed above).</p></dd><dt><span class="term">UINT32</span></dt><dd><p>num_entries (listed above)</p></dd></dl></div><p>return 0 - indicates success</p></div></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2867818"></a>NETLOGON rpc Transact Named Pipe</h2></div></div><div></div></div><p>The sequence of actions taken on this pipe are:</p><table class="simplelist" border="0" summary="Simple list"><tr><td>tablish a connection to the IPC$ share (SMBtconX). use encrypted passwords.</td></tr><tr><td>en an RPC Pipe with the name "\\PIPE\\NETLOGON". Store the file handle.</td></tr><tr><td>ing the file handle, send a Set Named Pipe Handle state to 0x4300.</td></tr><tr><td>eate Client Challenge. Send LSA Request Challenge. Store Server Challenge.</td></tr><tr><td>lculate Session Key. Send an LSA Auth 2 Challenge. Store Auth2 Challenge.</td></tr><tr><td>lc/Verify Client Creds. Send LSA Srv PW Set. Calc/Verify Server Creds.</td></tr><tr><td>lc/Verify Client Creds. Send LSA SAM Logon . Calc/Verify Server Creds.</td></tr><tr><td>lc/Verify Client Creds. Send LSA SAM Logoff. Calc/Verify Server Creds.</td></tr><tr><td>ose the IPC$ share.</td></tr></table><p>Defines for this pipe, identifying the query are</p><div class="variablelist"><dl><dt><span class="term">LSA Request Challenge:</span></dt><dd><p>0x04</p></dd><dt><span class="term">LSA Server Password Set:</span></dt><dd><p>0x06</p></dd><dt><span class="term">LSA SAM Logon:</span></dt><dd><p>0x02</p></dd><dt><span class="term">LSA SAM Logoff:</span></dt><dd><p>0x03</p></dd><dt><span class="term">LSA Auth 2:</span></dt><dd><p>0x0f</p></dd><dt><span class="term">LSA Logon Control:</span></dt><dd><p>0x0e</p></dd></dl></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2867980"></a>LSA Request Challenge</h3></div></div><div></div></div><p><span class="emphasis"><em>Note: logon server name starts with two '\' characters and is upper case.</em></span></p><p><span class="emphasis"><em>Note: logon client is the machine, not the user.</em></span></p><p><span class="emphasis"><em>Note: the initial LanManager password hash, against which the challenge is issued, is the machine name itself (lower case). there will becalls issued (LSA Server Password Set) which will change this, later. refusing these calls allows you to always deal with the same password (i.e the LM# of the machine name in lower case).</em></span></p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2868012"></a>Request</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">VOID*</span></dt><dd><p>undocumented buffer pointer</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>logon server unicode string</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>logon client unicode string</p></dd><dt><span class="term">char[8]</span></dt><dd><p>client challenge</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2868082"></a>Response</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">char[8]</span></dt><dd><p>server challenge</p></dd></dl></div><p>return 0 - indicates success</p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2868114"></a>LSA Authenticate 2</h3></div></div><div></div></div><p><span class="emphasis"><em>Note: in between request and response, calculate the client credentials, and check them against the client-calculated credentials (this process uses the previously received client credentials).</em></span></p><p><span class="emphasis"><em>Note: neg_flags in the response is the same as that in the request.</em></span></p><p><span class="emphasis"><em>Note: you must take a copy of the client-calculated credentials received here, because they will be used in subsequent authentication packets.</em></span></p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2868145"></a>Request</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">LOG_INFO</span></dt><dd><p>client identification info</p></dd><dt><span class="term">char[8]</span></dt><dd><p>client-calculated credentials</p></dd><dt><span class="term">UINT8[]</span></dt><dd><p>padding to 4-byte align with start of SMB header.</p></dd><dt><span class="term">UINT32</span></dt><dd><p>neg_flags - negotiated flags (usual value is 0x0000 01ff)</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2868214"></a>Response</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">char[8]</span></dt><dd><p>server credentials.</p></dd><dt><span class="term">UINT32</span></dt><dd><p>neg_flags - same as neg_flags in request.</p></dd></dl></div><p>return 0 - indicates success. failure value unknown.</p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2868261"></a>LSA Server Password Set</h3></div></div><div></div></div><p><span class="emphasis"><em>Note: the new password is suspected to be a DES encryption using the old password to generate the key.</em></span></p><p><span class="emphasis"><em>Note: in between request and response, calculate the client credentials, and check them against the client-calculated credentials (this process uses the previously received client credentials).</em></span></p><p><span class="emphasis"><em>Note: the server credentials are constructed from the client-calculated credentials and the client time + 1 second.</em></span></p><p><span class="emphasis"><em>Note: you must take a copy of the client-calculated credentials received here, because they will be used in subsequent authentication packets.</em></span></p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2868300"></a>Request</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">CLNT_INFO</span></dt><dd><p>client identification/authentication info</p></dd><dt><span class="term">char[]</span></dt><dd><p>new password - undocumented.</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2868342"></a>Response</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">CREDS</span></dt><dd><p>server credentials. server time stamp appears to be ignored.</p></dd></dl></div><p>return 0 - indicates success; 0xC000 006a indicates failure</p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2868376"></a>LSA SAM Logon</h3></div></div><div></div></div><p><span class="emphasis"><em>
Note: valid_user is True iff the username and password hash are valid for
the requested domain.
</em></span></p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2868390"></a>Request</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">SAM_INFO</span></dt><dd><p>sam_id structure</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2868417"></a>Response</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">VOID*</span></dt><dd><p>undocumented buffer pointer</p></dd><dt><span class="term">CREDS</span></dt><dd><p>server credentials. server time stamp appears to be ignored.</p></dd></dl></div><pre class="programlisting">
if (valid_user)
{
UINT16 3 - switch value indicating USER_INFO structure.
VOID* non-zero - pointer to USER_INFO structure
USER_INFO user logon information
UINT32 1 - Authoritative response; 0 - Non-Auth?
return 0 - indicates success
}
else
{
UINT16 0 - switch value. value to indicate no user presumed.
VOID* 0x0000 0000 - indicates no USER_INFO structure.
UINT32 1 - Authoritative response; 0 - Non-Auth?
return 0xC000 0064 - NT_STATUS_NO_SUCH_USER.
}
</pre></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2868479"></a>LSA SAM Logoff</h3></div></div><div></div></div><p><span class="emphasis"><em>
Note: presumably, the SAM_INFO structure is validated, and a (currently
undocumented) error code returned if the Logoff is invalid.
</em></span></p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2868494"></a>Request</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">SAM_INFO</span></dt><dd><p>sam_id structure</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2868521"></a>Response</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">VOID*</span></dt><dd><p>undocumented buffer pointer</p></dd><dt><span class="term">CREDS</span></dt><dd><p>server credentials. server time stamp appears to be ignored.</p></dd></dl></div><p>return 0 - indicates success. undocumented failure indication.</p></div></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2868571"></a>\\MAILSLOT\NET\NTLOGON</h2></div></div><div></div></div><p><span class="emphasis"><em>
Note: mailslots will contain a response mailslot, to which the response
should be sent. the target NetBIOS name is REQUEST_NAME<20>, where
REQUEST_NAME is the name of the machine that sent the request.
</em></span></p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2868583"></a>Query for PDC</h3></div></div><div></div></div><p><span class="emphasis"><em>Note: NTversion, LMNTtoken, LM20token in response are the same as those given in the request.</em></span></p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2868603"></a>Request</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UINT16</span></dt><dd><p>0x0007 - Query for PDC</p></dd><dt><span class="term">STR</span></dt><dd><p>machine name</p></dd><dt><span class="term">STR</span></dt><dd><p>response mailslot</p></dd><dt><span class="term">UINT8[]</span></dt><dd><p>padding to 2-byte align with start of mailslot.</p></dd><dt><span class="term">UNISTR</span></dt><dd><p>machine name</p></dd><dt><span class="term">UINT32</span></dt><dd><p>NTversion</p></dd><dt><span class="term">UINT16</span></dt><dd><p>LMNTtoken</p></dd><dt><span class="term">UINT16</span></dt><dd><p>LM20token</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2868729"></a>Response</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UINT16</span></dt><dd><p>0x000A - Respose to Query for PDC</p></dd><dt><span class="term">STR</span></dt><dd><p>machine name (in uppercase)</p></dd><dt><span class="term">UINT8[]</span></dt><dd><p>padding to 2-byte align with start of mailslot.</p></dd><dt><span class="term">UNISTR</span></dt><dd><p>machine name</p></dd><dt><span class="term">UNISTR</span></dt><dd><p>domain name</p></dd><dt><span class="term">UINT32</span></dt><dd><p>NTversion (same as received in request)</p></dd><dt><span class="term">UINT16</span></dt><dd><p>LMNTtoken (same as received in request)</p></dd><dt><span class="term">UINT16</span></dt><dd><p>LM20token (same as received in request)</p></dd></dl></div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2868850"></a>SAM Logon</h3></div></div><div></div></div><p><span class="emphasis"><em>Note: machine name in response is preceded by two '\' characters.</em></span></p><p><span class="emphasis"><em>Note: NTversion, LMNTtoken, LM20token in response are the same as those given in the request.</em></span></p><p><span class="emphasis"><em>Note: user name in the response is presumably the same as that in the request.</em></span></p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2868878"></a>Request</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UINT16</span></dt><dd><p>0x0012 - SAM Logon</p></dd><dt><span class="term">UINT16</span></dt><dd><p>request count</p></dd><dt><span class="term">UNISTR</span></dt><dd><p>machine name</p></dd><dt><span class="term">UNISTR</span></dt><dd><p>user name</p></dd><dt><span class="term">STR</span></dt><dd><p>response mailslot</p></dd><dt><span class="term">UINT32</span></dt><dd><p>alloweable account</p></dd><dt><span class="term">UINT32</span></dt><dd><p>domain SID size</p></dd><dt><span class="term">char[sid_size]</span></dt><dd><p>domain SID, of sid_size bytes.</p></dd><dt><span class="term">UINT8[]</span></dt><dd><p>???? padding to 4? 2? -byte align with start of mailslot.</p></dd><dt><span class="term">UINT32</span></dt><dd><p>NTversion</p></dd><dt><span class="term">UINT16</span></dt><dd><p>LMNTtoken</p></dd><dt><span class="term">UINT16</span></dt><dd><p>LM20token</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2877517"></a>Response</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UINT16</span></dt><dd><p>0x0013 - Response to SAM Logon</p></dd><dt><span class="term">UNISTR</span></dt><dd><p>machine name</p></dd><dt><span class="term">UNISTR</span></dt><dd><p>user name - workstation trust account</p></dd><dt><span class="term">UNISTR</span></dt><dd><p>domain name </p></dd><dt><span class="term">UINT32</span></dt><dd><p>NTversion</p></dd><dt><span class="term">UINT16</span></dt><dd><p>LMNTtoken</p></dd><dt><span class="term">UINT16</span></dt><dd><p>LM20token</p></dd></dl></div></div></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2877631"></a>SRVSVC Transact Named Pipe</h2></div></div><div></div></div><p>Defines for this pipe, identifying the query are:</p><div class="variablelist"><dl><dt><span class="term">Net Share Enum</span></dt><dd><p>0x0f</p></dd><dt><span class="term">Net Server Get Info</span></dt><dd><p>0x15</p></dd></dl></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2877676"></a>Net Share Enum</h3></div></div><div></div></div><p><span class="emphasis"><em>Note: share level and switch value in the response are presumably the same as those in the request.</em></span></p><p><span class="emphasis"><em>Note: cifsrap2.txt (section 5) may be of limited assistance here.</em></span></p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2877697"></a>Request</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">VOID*</span></dt><dd><p>pointer (to server name?)</p></dd><dt><span class="term">UNISTR2</span></dt><dd><p>server name</p></dd><dt><span class="term">UINT8[]</span></dt><dd><p>padding to get unicode string 4-byte aligned with the start of the SMB header.</p></dd><dt><span class="term">UINT32</span></dt><dd><p>share level</p></dd><dt><span class="term">UINT32</span></dt><dd><p>switch value</p></dd><dt><span class="term">VOID*</span></dt><dd><p>pointer to SHARE_INFO_1_CTR</p></dd><dt><span class="term">SHARE_INFO_1_CTR</span></dt><dd><p>share info with 0 entries</p></dd><dt><span class="term">UINT32</span></dt><dd><p>preferred maximum length (0xffff ffff)</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2877823"></a>Response</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UINT32</span></dt><dd><p>share level</p></dd><dt><span class="term">UINT32</span></dt><dd><p>switch value</p></dd><dt><span class="term">VOID*</span></dt><dd><p>pointer to SHARE_INFO_1_CTR</p></dd><dt><span class="term">SHARE_INFO_1_CTR</span></dt><dd><p>share info (only added if share info ptr is non-zero)</p></dd></dl></div><p>return 0 - indicates success</p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2877896"></a>Net Server Get Info</h3></div></div><div></div></div><p><span class="emphasis"><em>Note: level is the same value as in the request.</em></span></p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2877909"></a>Request</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UNISTR2</span></dt><dd><p>server name</p></dd><dt><span class="term">UINT32</span></dt><dd><p>switch level</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2877950"></a>Response</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">UINT32</span></dt><dd><p>switch level</p></dd><dt><span class="term">VOID*</span></dt><dd><p>pointer to SERVER_INFO_101</p></dd><dt><span class="term">SERVER_INFO_101</span></dt><dd><p>server info (only added if server info ptr is non-zero)</p></dd></dl></div><p>return 0 - indicates success</p></div></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2878012"></a>Cryptographic side of NT Domain Authentication</h2></div></div><div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2878020"></a>Definitions</h3></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">Add(A1,A2)</span></dt><dd><p>Intel byte ordered addition of corresponding 4 byte words in arrays A1 and A2</p></dd><dt><span class="term">E(K,D)</span></dt><dd><p>DES ECB encryption of 8 byte data D using 7 byte key K</p></dd><dt><span class="term">lmowf()</span></dt><dd><p>Lan man hash</p></dd><dt><span class="term">ntowf()</span></dt><dd><p>NT hash</p></dd><dt><span class="term">PW</span></dt><dd><p>md4(machine_password) == md4(lsadump $machine.acc) ==
pwdump(machine$) (initially) == md4(lmowf(unicode(machine)))
</p></dd><dt><span class="term">ARC4(K,Lk,D,Ld)</span></dt><dd><p>ARC4 encryption of data D of length Ld with key K of length Lk</p></dd><dt><span class="term">v[m..n(,l)]</span></dt><dd><p>subset of v from bytes m to n, optionally padded with zeroes to length l</p></dd><dt><span class="term">Cred(K,D)</span></dt><dd><p>E(K[7..7,7],E(K[0..6],D)) computes a credential</p></dd><dt><span class="term">Time()</span></dt><dd><p>4 byte current time</p></dd><dt><span class="term">Cc,Cs</span></dt><dd><p>8 byte client and server challenges Rc,Rs: 8 byte client and server credentials</p></dd></dl></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2878182"></a>Protocol</h3></div></div><div></div></div><pre class="programlisting">
C->S ReqChal,Cc
S->C Cs
</pre><pre class="programlisting">
C & S compute session key Ks = E(PW[9..15],E(PW[0..6],Add(Cc,Cs)))
</pre><pre class="programlisting">
C: Rc = Cred(Ks,Cc)
C->S Authenticate,Rc
S: Rs = Cred(Ks,Cs), assert(Rc == Cred(Ks,Cc))
S->C Rs
C: assert(Rs == Cred(Ks,Cs))
</pre><p>
On joining the domain the client will optionally attempt to change its
password and the domain controller may refuse to update it depending
on registry settings. This will also occur weekly afterwards.
</p><pre class="programlisting">
C: Tc = Time(), Rc' = Cred(Ks,Rc+Tc)
C->S ServerPasswordSet,Rc',Tc,arc4(Ks[0..7,16],lmowf(randompassword())
C: Rc = Cred(Ks,Rc+Tc+1)
S: assert(Rc' == Cred(Ks,Rc+Tc)), Ts = Time()
S: Rs' = Cred(Ks,Rs+Tc+1)
S->C Rs',Ts
C: assert(Rs' == Cred(Ks,Rs+Tc+1))
S: Rs = Rs'
</pre><p>
User: U with password P wishes to login to the domain (incidental data
such as workstation and domain omitted)
</p><pre class="programlisting">
C: Tc = Time(), Rc' = Cred(Ks,Rc+Tc)
C->S NetLogonSamLogon,Rc',Tc,U,arc4(Ks[0..7,16],16,ntowf(P),16), arc4(Ks[0..7,16],16,lmowf(P),16)
S: assert(Rc' == Cred(Ks,Rc+Tc)) assert(passwords match those in SAM)
S: Ts = Time()
</pre><pre class="programlisting">
S->C Cred(Ks,Cred(Ks,Rc+Tc+1)),userinfo(logon script,UID,SIDs,etc)
C: assert(Rs == Cred(Ks,Cred(Rc+Tc+1))
C: Rc = Cred(Ks,Rc+Tc+1)
</pre></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2878280"></a>Comments</h3></div></div><div></div></div><p>
On first joining the domain the session key could be computed by
anyone listening in on the network as the machine password has a well
known value. Until the machine is rebooted it will use this session
key to encrypt NT and LM one way functions of passwords which are
password equivalents. Any user who logs in before the machine has been
rebooted a second time will have their password equivalent exposed. Of
course the new machine password is exposed at this time anyway.
</p><p>
None of the returned user info such as logon script, profile path and
SIDs *appear* to be protected by anything other than the TCP checksum.
</p><p>
The server time stamps appear to be ignored.
</p><p>
The client sends a ReturnAuthenticator in the SamLogon request which I
can't find a use for. However its time is used as the timestamp
returned by the server.
</p><p>
The password OWFs should NOT be sent over the network reversibly
encrypted. They should be sent using ARC4(Ks,md4(owf)) with the server
computing the same function using the owf values in the SAM.
</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2878330"></a>SIDs and RIDs</h2></div></div><div></div></div><p>
SIDs and RIDs are well documented elsewhere.
</p><p>
A SID is an NT Security ID (see DOM_SID structure). They are of the form:
</p><table class="simplelist" border="0" summary="Simple list"><tr><td>revision-NN-SubAuth1-SubAuth2-SubAuth3... </td></tr><tr><td>revision-0xNNNNNNNNNNNN-SubAuth1-SubAuth2-SubAuth3...</td></tr></table><p>
currently, the SID revision is 1.
The Sub-Authorities are known as Relative IDs (RIDs).
</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2878368"></a>Well-known SIDs</h3></div></div><div></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2878375"></a>Universal well-known SIDs</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">Null SID</span></dt><dd><p>S-1-0-0</p></dd><dt><span class="term">World</span></dt><dd><p>S-1-1-0</p></dd><dt><span class="term">Local</span></dt><dd><p>S-1-2-0</p></dd><dt><span class="term">Creator Owner ID</span></dt><dd><p>S-1-3-0</p></dd><dt><span class="term">Creator Group ID</span></dt><dd><p>S-1-3-1</p></dd><dt><span class="term">Creator Owner Server ID</span></dt><dd><p>S-1-3-2</p></dd><dt><span class="term">Creator Group Server ID</span></dt><dd><p>S-1-3-3</p></dd><dt><span class="term">(Non-unique IDs)</span></dt><dd><p>S-1-4</p></dd></dl></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2878502"></a>NT well-known SIDs</h4></div></div><div></div></div><div class="variablelist"><dl><dt><span class="term">NT Authority</span></dt><dd><p>S-1-5</p></dd><dt><span class="term">Dialup</span></dt><dd><p>S-1-5-1</p></dd><dt><span class="term">Network</span></dt><dd><p>S-1-5-2</p></dd><dt><span class="term">Batch</span></dt><dd><p>S-1-5-3</p></dd><dt><span class="term">Interactive</span></dt><dd><p>S-1-5-4</p></dd><dt><span class="term">Service</span></dt><dd><p>S-1-5-6</p></dd><dt><span class="term">AnonymousLogon(aka null logon session)</span></dt><dd><p>S-1-5-7</p></dd><dt><span class="term">Proxy</span></dt><dd><p>S-1-5-8</p></dd><dt><span class="term">ServerLogon(aka domain controller account)</span></dt><dd><p>S-1-5-8</p></dd><dt><span class="term">(Logon IDs)</span></dt><dd><p>S-1-5-5-X-Y</p></dd><dt><span class="term">(NT non-unique IDs)</span></dt><dd><p>S-1-5-0x15-...</p></dd><dt><span class="term">(Built-in domain)</span></dt><dd><p>s-1-5-0x20</p></dd></dl></div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2878683"></a>Well-known RIDS</h3></div></div><div></div></div><p>
A RID is a sub-authority value, as part of either a SID, or in the case
of Group RIDs, part of the DOM_GID structure, in the USER_INFO_1
structure, in the LSA SAM Logon response.
</p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2878697"></a>Well-known RID users</h4></div></div><div></div></div><div class="segmentedlist"><p><b>Groupname: </b>DOMAIN_USER_RID_ADMIN</p><p><b>????: </b>0x0000</p><p><b>RID: </b>01F4</p><p><b>Groupname: </b>DOMAIN_USER_RID_GUEST</p><p><b>????: </b>0x0000</p><p><b>RID: </b>01F5</p></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2878745"></a>Well-known RID groups</h4></div></div><div></div></div><div class="segmentedlist"><p><b>Groupname: </b> DOMAIN_GROUP_RID_ADMINS</p><p><b>????: </b>0x0000</p><p><b>RID: </b>0200</p><p><b>Groupname: </b> DOMAIN_GROUP_RID_USERS</p><p><b>????: </b>0x0000</p><p><b>RID: </b>0201</p><p><b>Groupname: </b> DOMAIN_GROUP_RID_GUESTS</p><p><b>????: </b>0x0000</p><p><b>RID: </b>0202</p></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="id2878805"></a>Well-known RID aliases</h4></div></div><div></div></div><div class="segmentedlist"><p><b>Groupname: </b> DOMAIN_ALIAS_RID_ADMINS</p><p><b>????: </b>0x0000</p><p><b>RID: </b>0220</p><p><b>Groupname: </b> DOMAIN_ALIAS_RID_USERS</p><p><b>????: </b>0x0000</p><p><b>RID: </b>0221</p><p><b>Groupname: </b> DOMAIN_ALIAS_RID_GUESTS</p><p><b>????: </b>0x0000</p><p><b>RID: </b>0222</p><p><b>Groupname: </b> DOMAIN_ALIAS_RID_POWER_USERS</p><p><b>????: </b>0x0000</p><p><b>RID: </b>0223</p><p><b>Groupname: </b> DOMAIN_ALIAS_RID_ACCOUNT_OPS</p><p><b>????: </b>0x0000</p><p><b>RID: </b>0224</p><p><b>Groupname: </b> DOMAIN_ALIAS_RID_SYSTEM_OPS</p><p><b>????: </b>0x0000</p><p><b>RID: </b>0225</p><p><b>Groupname: </b> DOMAIN_ALIAS_RID_PRINT_OPS</p><p><b>????: </b>0x0000</p><p><b>RID: </b>0226</p><p><b>Groupname: </b> DOMAIN_ALIAS_RID_BACKUP_OPS</p><p><b>????: </b>0x0000</p><p><b>RID: </b>0227</p><p><b>Groupname: </b> DOMAIN_ALIAS_RID_REPLICATOR</p><p><b>????: </b>0x0000</p><p><b>RID: </b>0228</p></div></div></div></div></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="printing"></a>Chapter 11. Samba Printing Internals</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Gerald</span> <span class="surname">Carter</span></h3></div></div><div><p class="pubdate">October 2002</p></div></div><div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><a href="#id2878968">Abstract</a></dt><dt><a href="#id2878984">
Printing Interface to Various Back ends
</a></dt><dt><a href="#id2879080">
Print Queue TDB's
</a></dt><dt><a href="#id2879295">
ChangeID and Client Caching of Printer Information
</a></dt><dt><a href="#id2879308">
Windows NT/2K Printer Change Notify
</a></dt></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2878968"></a>Abstract</h2></div></div><div></div></div><p>
The purpose of this document is to provide some insight into
Samba's printing functionality and also to describe the semantics
of certain features of Windows client printing.
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2878984"></a>
Printing Interface to Various Back ends
</h2></div></div><div></div></div><p>
Samba uses a table of function pointers to seven functions. The
function prototypes are defined in the <tt class="varname">printif</tt> structure declared
in <tt class="filename">printing.h</tt>.
</p><div class="itemizedlist"><ul type="disc"><li><p>retrieve the contents of a print queue</p></li><li><p>pause the print queue</p></li><li><p>resume a paused print queue</p></li><li><p>delete a job from the queue</p></li><li><p>pause a job in the print queue</p></li><li><p>result a paused print job in the queue</p></li><li><p>submit a job to the print queue</p></li></ul></div><p>
Currently there are only two printing back end implementations
defined.
</p><div class="itemizedlist"><ul type="disc"><li><p>a generic set of functions for working with standard UNIX
printing subsystems</p></li><li><p>a set of CUPS specific functions (this is only enabled if
the CUPS libraries were located at compile time).</p></li></ul></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2879080"></a>
Print Queue TDB's
</h2></div></div><div></div></div><p>
Samba provides periodic caching of the output from the "lpq command"
for performance reasons. This cache time is configurable in seconds.
Obviously the longer the cache time the less often smbd will be
required to exec a copy of lpq. However, the accuracy of the print
queue contents displayed to clients will be diminished as well.
</p><p>
The list of currently opened print queue TDB's can be found
be examining the list of tdb_print_db structures ( see print_db_head
in printing.c ). A queue TDB is opened using the wrapper function
printing.c:get_print_db_byname(). The function ensures that smbd
does not open more than MAX_PRINT_DBS_OPEN in an effort to prevent
a large print server from exhausting all available file descriptors.
If the number of open queue TDB's exceeds the MAX_PRINT_DBS_OPEN
limit, smbd falls back to a most recently used algorithm for maintaining
a list of open TDB's.
</p><p>
There are two ways in which a a print job can be entered into
a print queue's TDB. The first is to submit the job from a Windows
client which will insert the job information directly into the TDB.
The second method is to have the print job picked up by executing the
"lpq command".
</p><pre class="programlisting">
/* included from printing.h */
struct printjob {
pid_t pid; /* which process launched the job */
int sysjob; /* the system (lp) job number */
int fd; /* file descriptor of open file if open */
time_t starttime; /* when the job started spooling */
int status; /* the status of this job */
size_t size; /* the size of the job so far */
int page_count; /* then number of pages so far */
BOOL spooled; /* has it been sent to the spooler yet? */
BOOL smbjob; /* set if the job is a SMB job */
fstring filename; /* the filename used to spool the file */
fstring jobname; /* the job name given to us by the client */
fstring user; /* the user who started the job */
fstring queuename; /* service number of printer for this job */
NT_DEVICEMODE *nt_devmode;
};
</pre><p>
The current manifestation of the printjob structure contains a field
for the UNIX job id returned from the "lpq command" and a Windows job
ID (32-bit bounded by PRINT_MAX_JOBID). When a print job is returned
by the "lpq command" that does not match an existing job in the queue's
TDB, a 32-bit job ID above the <*vance doesn't know what word is missing here*> is generating by adding UNIX_JOB_START to
the id reported by lpq.
</p><p>
In order to match a 32-bit Windows jobid onto a 16-bit lanman print job
id, smbd uses an in memory TDB to match the former to a number appropriate
for old lanman clients.
</p><p>
When updating a print queue, smbd will perform the following
steps ( refer to <tt class="filename">print.c:print_queue_update()</tt> ):
</p><div class="orderedlist"><ol type="1"><li><p>Check to see if another smbd is currently in
the process of updating the queue contents by checking the pid
stored in <tt class="constant">LOCK/<i class="replaceable"><tt>printer_name</tt></i></tt>.
If so, then do not update the TDB.</p></li><li><p>Lock the mutex entry in the TDB and store our own pid.
Check that this succeeded, else fail.</p></li><li><p>Store the updated time stamp for the new cache
listing</p></li><li><p>Retrieve the queue listing via "lpq command"</p></li><li><pre class="programlisting">
foreach job in the queue
{
if the job is a UNIX job, create a new entry;
if the job has a Windows based jobid, then
{
Lookup the record by the jobid;
if the lookup failed, then
treat it as a UNIX job;
else
update the job status only
}
}</pre></li><li><p>Delete any jobs in the TDB that are not
in the in the lpq listing</p></li><li><p>Store the print queue status in the TDB</p></li><li><p>update the cache time stamp again</p></li></ol></div><p>
Note that it is the contents of this TDB that is returned to Windows
clients and not the actual listing from the "lpq command".
</p><p>
The NT_DEVICEMODE stored as part of the printjob structure is used to
store a pointer to a non-default DeviceMode associated with the print
job. The pointer will be non-null when the client included a Device
Mode in the OpenPrinterEx() call and subsequently submitted a job for
printing on that same handle. If the client did not include a Device
Mode in the OpenPrinterEx() request, the nt_devmode field is NULL
and the job has the printer's device mode associated with it by default.
</p><p>
Only non-default Device Mode are stored with print jobs in the print
queue TDB. Otherwise, the Device Mode is obtained from the printer
object when the client issues a GetJob(level == 2) request.
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2879295"></a>
ChangeID and Client Caching of Printer Information
</h2></div></div><div></div></div><p>
[To be filled in later]
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2879308"></a>
Windows NT/2K Printer Change Notify
</h2></div></div><div></div></div><p>
When working with Windows NT+ clients, it is possible for a
print server to use RPC to send asynchronous change notification
events to clients for certain printer and print job attributes.
This can be useful when the client needs to know that a new
job has been added to the queue for a given printer or that the
driver for a printer has been changed. Note that this is done
entirely orthogonal to cache updates based on a new ChangeID for
a printer object.
</p><p>
The basic set of RPC's used to implement change notification are
</p><div class="itemizedlist"><ul type="disc"><li><p>RemoteFindFirstPrinterChangeNotifyEx ( RFFPCN )</p></li><li><p>RemoteFindNextPrinterChangeNotifyEx ( RFNPCN )</p></li><li><p>FindClosePrinterChangeNotify( FCPCN )</p></li><li><p>ReplyOpenPrinter</p></li><li><p>ReplyClosePrinter</p></li><li><p>RouteRefreshPrinterChangeNotify ( RRPCN )</p></li></ul></div><p>
One additional RPC is available to a server, but is never used by the
Windows spooler service:
</p><div class="itemizedlist"><ul type="disc"><li><p>RouteReplyPrinter()</p></li></ul></div><p>
The opnum for all of these RPC's are defined in include/rpc_spoolss.h
</p><p>
Windows NT print servers use a bizarre method of sending print
notification event to clients. The process of registering a new change
notification handle is as follows. The 'C' is for client and the
'S' is for server. All error conditions have been eliminated.
</p><pre class="programlisting">
C: Obtain handle to printer or to the printer
server via the standard OpenPrinterEx() call.
S: Respond with a valid handle to object
C: Send a RFFPCN request with the previously obtained
handle with either (a) set of flags for change events
to monitor, or (b) a PRINTER_NOTIFY_OPTIONS structure
containing the event information to monitor. The windows
spooler has only been observed to use (b).
S: The <* another missing word*> opens a new TCP session to the client (thus requiring
all print clients to be CIFS servers as well) and sends
a ReplyOpenPrinter() request to the client.
C: The client responds with a printer handle that can be used to
send event notification messages.
S: The server replies success to the RFFPCN request.
C: The windows spooler follows the RFFPCN with a RFNPCN
request to fetch the current values of all monitored
attributes.
S: The server replies with an array SPOOL_NOTIFY_INFO_DATA
structures (contained in a SPOOL_NOTIFY_INFO structure).
C: If the change notification handle is ever released by the
client via a FCPCN request, the server sends a ReplyClosePrinter()
request back to the client first. However a request of this
nature from the client is often an indication that the previous
notification event was not marshalled correctly by the server
or a piece of data was wrong.
S: The server closes the internal change notification handle
(POLICY_HND) and does not send any further change notification
events to the client for that printer or job.
</pre><p>
The current list of notification events supported by Samba can be
found by examining the internal tables in srv_spoolss_nt.c
</p><div class="itemizedlist"><ul type="disc"><li><p>printer_notify_table[]</p></li><li><p>job_notify_table[]</p></li></ul></div><p>
When an event occurs that could be monitored, smbd sends a message
to itself about the change. The list of events to be transmitted
are queued by the smbd process sending the message to prevent an
overload of TDB usage and the internal message is sent during smbd's
idle loop (refer to printing/notify.c and the functions
send_spoolss_notify2_msg() and print_notify_send_messages() ).
</p><p>
The decision of whether or not the change is to be sent to connected
clients is made by the routine which actually sends the notification.
( refer to srv_spoolss_nt.c:recieve_notify2_message() ).
</p><p>
Because it possible to receive a listing of multiple changes for
multiple printers, the notification events must be split into
categories by the printer name. This makes it possible to group
multiple change events to be sent in a single RPC according to the
printer handle obtained via a ReplyOpenPrinter().
</p><p>
The actual change notification is performed using the RRPCN request
RPC. This packet contains
</p><div class="itemizedlist"><ul type="disc"><li><p>the printer handle registered with the
client's spooler on which the change occurred</p></li><li><p>The change_low value which was sent as part
of the last RFNPCN request from the client</p></li><li><p>The SPOOL_NOTIFY_INFO container with the event
information</p></li></ul></div><p>
A <tt class="varname">SPOOL_NOTIFY_INFO</tt> contains:
</p><div class="itemizedlist"><ul type="disc"><li><p>the version and flags field are predefined
and should not be changed</p></li><li><p>The count field is the number of entries
in the SPOOL_NOTIFY_INFO_DATA array</p></li></ul></div><p>
The <tt class="varname">SPOOL_NOTIFY_INFO_DATA</tt> entries contain:
</p><div class="itemizedlist"><ul type="disc"><li><p>The type defines whether or not this event
is for a printer or a print job</p></li><li><p>The field is the flag identifying the event</p></li><li><p>the notify_data union contains the new valuie of the
attribute</p></li><li><p>The enc_type defines the size of the structure for marshalling
and unmarshalling</p></li><li><p>(a) the id must be 0 for a printer event on a printer handle.
(b) the id must be the job id for an event on a printer job
(c) the id must be the matching number of the printer index used
in the response packet to the RFNPCN when using a print server
handle for notification. Samba currently uses the snum of
the printer for this which can break if the list of services
has been modified since the notification handle was registered.</p></li><li><p>The size is either (a) the string length in UNICODE for strings,
(b) the size in bytes of the security descriptor, or (c) 0 for
data values.</p></li></ul></div></div></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="wins"></a>Chapter 12. Samba WINS Internals</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Gerald</span> <span class="surname">Carter</span></h3></div></div><div><p class="pubdate">October 2002</p></div></div><div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><a href="#id2879669">WINS Failover</a></dt></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2879669"></a>WINS Failover</h2></div></div><div></div></div><p>
The current Samba codebase possesses the capability to use groups of WINS
servers that share a common namespace for NetBIOS name registration and
resolution. The formal parameter syntax is
</p><pre class="programlisting">
WINS_SERVER_PARAM = SERVER [ SEPARATOR SERVER_LIST ]
WINS_SERVER_PARAM = "wins server"
SERVER = ADDR[:TAG]
ADDR = ip_addr | fqdn
TAG = string
SEPARATOR = comma | \s+
SERVER_LIST = SERVER [ SEPARATOR SERVER_LIST ]
</pre><p>
A simple example of a valid wins server setting is
</p><pre class="programlisting">
[global]
wins server = 192.168.1.2 192.168.1.3
</pre><p>
In the event that no TAG is defined in for a SERVER in the list, smbd assigns a default
TAG of "*". A TAG is used to group servers of a shared NetBIOS namespace together. Upon
startup, nmbd will attempt to register the netbios name value with one server in each
tagged group.
</p><p>
An example using tags to group WINS servers together is show here. Note that the use of
interface names in the tags is only by convention and is not a technical requirement.
</p><pre class="programlisting">
[global]
wins server = 192.168.1.2:eth0 192.168.1.3:eth0 192.168.2.2:eth1
</pre><p>
Using this configuration, nmbd would attempt to register the server's NetBIOS name
with one WINS server in each group. Because the "eth0" group has two servers, the
second server would only be used when a registration (or resolution) request to
the first server in that group timed out.
</p><p>
NetBIOS name resolution follows a similar pattern as name registration. When resolving
a NetBIOS name via WINS, smbd and other Samba programs will attempt to query a single WINS
server in a tagged group until either a positive response is obtained at least once or
until a server from every tagged group has responded negatively to the name query request.
If a timeout occurs when querying a specific WINS server, that server is marked as down to
prevent further timeouts and the next server in the WINS group is contacted. Once marked as
dead, Samba will not attempt to contact that server for name registration/resolution queries
for a period of 10 minutes.
</p></div></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="sam"></a>Chapter 13. The Upcoming SAM System</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Andrew</span> <span class="surname">Bartlett</span></h3></div></div><div><p class="pubdate">1 October 2002</p></div></div><div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><a href="#id2879798">Security in the 'new SAM'</a></dt><dt><a href="#id2879928">Standalone from UNIX</a></dt><dt><a href="#id2879955">Handles and Races in the new SAM</a></dt><dt><a href="#id2880024">Layers</a></dt><dd><dl><dt><a href="#id2880031">Application</a></dt><dt><a href="#id2880047">SAM Interface</a></dt><dt><a href="#id2880075">SAM Modules</a></dt></dl></dd><dt><a href="#id2880097">SAM Modules</a></dt><dd><dl><dt><a href="#id2880104">Special Module: sam_passdb</a></dt><dt><a href="#id2880122">sam_ads</a></dt></dl></dd><dt><a href="#id2880151">Memory Management</a></dt><dt><a href="#id2880242">Testing</a></dt></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2879798"></a>Security in the 'new SAM'</h2></div></div><div></div></div><p>One of the biggest problems with passdb is it's implementation of
'security'. Access control is on a 'are you root at the moment' basis,
and it has no concept of NT ACLs. Things like ldapsam had to add
'magic' 'are you root' checks.</p><p>We took this very seriously when we started work, and the new structure
is designed with this in mind, from the ground up. Each call to the SAM
has a NT_TOKEN and (if relevant) an 'access desired'. This is either
provided as a parameter, or implicitly supplied by the object being
accessed.</p><p>
For example, when you call
</p><pre class="programlisting">
NTSTATUS sam_get_account_by_name(const SAM_CONTEXT *context, const
NT_USER_TOKEN *access_token, uint32 access_desired, const char *domain,
const char *name, SAM_ACCOUNT_HANDLE **account)
</pre><p>
The context can be NULL (and is used to allow import/export by setting
up 2 contexts, and allowing calls on both simultaneously)
</p><p>
The access token *must* be specified. Normally the user's token out of
current_user, this can also be a global 'system' context.
</p><p>
The access desired is as per the ACL, for passing to the seaccess stuff.
</p><p>
The domain/username are standard. Even if we only have one domain,
keeping this ensures that we don't get 'unqualified' usernames (same
problem as we had with unqualified SIDs).
</p><p>
We return a 'handle'. This is opaque to the rest of Samba, but is
operated on by get/set routines, all of which return NTSTATUS.
</p><p>
The access checking is done by the SAM module. The reason it is not
done 'above' the interface is to ensure a 'choke point'. I put a lot of
effort into the auth subsystem to ensure we never 'accidentally' forgot
to check for null passwords, missed a restriction etc. I intend the SAM
to be written with the same caution.
</p><p>
The reason the access checking is not handled by the interface itself is
due to the different implementations it make take on. For example, on
ADS, you cannot set a password over a non-SSL connection. Other
backends may have similar requirements - we need to leave this policy up
to the modules. They will naturally have access to 'helper' procedures
and good examples to avoid mishaps.
</p><p>
(Furthermore, some backends my actually chose to push the whole ACL
issue to the remote server, and - assuming ldap for this example - bind
as the user directly)
</p><p>
Each returned handle has an internal 'access permitted', which allows
the 'get' and 'set' routines to return 'ACCESS_DENIED' for things that
were not able to be retrieved from the backend. This removes the need
to specify the NT_TOKEN on every operation, and allows for 'object not
present' to be easily distinguished from 'access denied'.
</p><p>
When you 'set' an object (calling sam_update_account) the internal
details are again used. Each change that has been made to the object
has been flagged, so as to avoid race conditions (on unmodified
components) and to avoid violating any extra ACL requirements on the
actual data store (like the LDAP server).
</p><p>
Finally, we have generic get_sec_desc() and set_sec_desc() routines to
allow external ACL manipulation. These do lookups based on SID.
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2879928"></a>Standalone from UNIX</h2></div></div><div></div></div><p>
One of the primary tenants of the 'new SAM' is that it would not attempt
to deal with 'what unix id for that'. This would be left to the 'SMS'
(Sid Mapping System') or SID farm, and probably administered via
winbind. We have had constructive discussion on how 'basic' unix
accounts like 'root' would be handled, and we think this can work.
Accounts not preexisting in unix would be served up via winbind.
</p><p>
This is an *optional* part, and my preferred end-game. We have a fare
way to go before things like winbind up to it however.
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2879955"></a>Handles and Races in the new SAM</h2></div></div><div></div></div><p>
One of the things that the 'new SAM' work has tried to face is both
compatibility with existing code, and a closer alignment to the SAMR
interface. I consider SAMR to be a 'primary customer' to the this work,
because if we get alignment with that wrong, things get more, rather
than less complex. Also, most other parts of Samba are much more
flexible with what they can allow.
</p><p>
In any case, that was a decision taken as to how the general design
would progress. BTW, my understanding of SAMR may be completely flawed.
</p><p>
One of the most race-prone areas of the new code is the conflicting
update problem. We have taken two approaches:
</p><div class="itemizedlist"><ul type="disc"><li><p>'Not conflicting' conflicts. Due to the way usrmgr operates, it will
open a user, display all the properties and *save* them all, even if you
don't change any.
</p><p>
For this, see what I've done in rpc_server/srv_samr_util.c. I intend
to take this one step further, and operate on the 'handle' that the
values were read from. This should mean that we only update things that
have *really* changed.
</p></li><li><p>
'conflicting' updates: Currently we don't deal with this (in passdb
or the new sam stuff), but the design is sufficiently flexible to 'deny'
a second update. I don't foresee locking records however.
</p></li></ul></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2880024"></a>Layers</h2></div></div><div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2880031"></a>Application</h3></div></div><div></div></div><p>
This is where smbd, samtest and whatever end-user replacement we have
for pdbedit sits. They use only the SAM interface, and do not get
'special knowledge' of what is below them.
</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2880047"></a>SAM Interface</h3></div></div><div></div></div><p>
This level 'owns' the various handle structures, the get/set routines on
those structures and provides the public interface. The application
layer may initialize a 'context' to be passed to all interface routines,
else a default, self-initialising context will be supplied. This layser
finds the appropriate backend module for the task, and tries very hard
not to need to much 'knowledge'. It should just provide the required
abstraction to the modules below, and arrange for their initial loading.
</p><p>
We could possibly add ACL checking at this layer, to avoid discrepancies
in implementation modules.
</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2880075"></a>SAM Modules</h3></div></div><div></div></div><p>
These do not communicate with the application directly, only by setting
values in the handles, and receiving requests from the interface. These
modules are responsible for translating values from the handle's
.private into (say) an LDAP modification list. The module is expected
to 'know' things like it's own domain SID, domain name, and any other
state attached to the SAM. Simpler modules may call back to some helper
routine.
</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2880097"></a>SAM Modules</h2></div></div><div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2880104"></a>Special Module: sam_passdb</h3></div></div><div></div></div><p>
In order for there to be a smooth transition, kai is writing a module
that reads existing passdb backends, and translates them into SAM
replies. (Also pulling data from the account policy DB etc). We also
intend to write a module that does the reverse - gives the SAM a passdb
interface.
</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2880122"></a>sam_ads</h3></div></div><div></div></div><p>
This is the first of the SAM modules to be committed to the tree -
mainly because I needed to coordinate work with metze (who authored most
of it). This module aims to use Samba's libads code to provide an
Active Directory LDAP client, suitable for use on a mixed-mode DC.
While it is currently being tested against Win2k servers (with a
password in the smb.conf file) it is expected to eventually use a
(possibly modified) OpenLDAP server. We hope that this will assist in
the construction of an Samba AD DC.
</p><p>
We also intend to construct a Samba 2.2/3.0 compatible ldap module,
again using libads code.
</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2880151"></a>Memory Management</h2></div></div><div></div></div><p>
The 'new SAM' development effort also concerned itself with getting a
sane implementation of memory management. It was decided that we would
be (as much as possible) talloc based, using an 'internal talloc
context' on many objects. That is, the creation of an object would
initiate it's own internal talloc context, and this would be used for
all operations on that object. Much of this is already implemented in
passdb. Also, like passdb, it will be possible to specify that some
object actually be created on a specified context.
</p><p>
Memory management is important here because the APIs in the 'new SAM' do
not use 'pdb_init()' or an equivalent. They always allocate new
objects. Enumeration's are slightly different, and occur on a supplied
context that 'owns' the entire list, rather than per-element. (the
enumeration functions return an array of all elements - not full handles
just basic (and public) info) Likewise for things that fill in a char
**.
</p><p>For example:</p><pre class="programlisting">
NTSTATUS sam_lookup_sid(const SAM_CONTEXT *context, const NT_USER_TOKEN
*access_token, TALLOC_CTX *mem_ctx, const DOM_SID *sid, char **name,
uint32 *type)
</pre><p>Takes a context to allocate the 'name' on, while:</p><pre class="programlisting">
NTSTATUS sam_get_account_by_sid(const SAM_CONTEXT *context, const
NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID
*accountsid, SAM_ACCOUNT_HANDLE **account)
</pre><p>Allocates a handle and stores the allocation context on that handle.</p><p>I think that the following:</p><pre class="programlisting">
NTSTATUS sam_enum_accounts(const SAM_CONTEXT *context, const
NT_USER_TOKEN *access_token, const DOM_SID *domainsid, uint16 acct_ctrl,
int32 *account_count, SAM_ACCOUNT_ENUM **accounts)
</pre></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2880242"></a>Testing</h2></div></div><div></div></div><p>
Testing is vital in any piece of software, and Samba is certainly no
exception. In designing this new subsystem, we have taken care to ensure
it is easily tested, independent of outside protocols.
</p><p>
To this end, Jelmer has constructed 'samtest'.
</p><p>
This utility (see torture/samtest.c) is structured like rpcclient, but
instead operates on the SAM subsystem. It creates a 'custom' SAM
context, that may be distinct from the default values used by the rest
of the system, and can load a separate configuration file.
</p><p>
A small number of commands are currently implemented, but these have
already proved vital in testing. I expect SAM module authors will find
it particularly valuable.
</p><p>Example useage:</p><p><tt class="prompt">$</tt> <b class="command">bin/samtest</b></p><pre class="programlisting">
> context ads:ldap://192.168.1.96
</pre><p>
(this loads a new context, using the new ADS module. The parameter is
the 'location' of the ldap server)
</p><pre class="programlisting">
> lookup_name DOMAIN abartlet
</pre><p>
(returns a sid).
</p><p>
Because the 'new SAM' is NT ACL based, there will be a command to
specify an arbitrary NT ACL, but for now it uses 'system' by default.
</p></div></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="pwencrypt"></a>Chapter 14. LanMan and NT Password Encryption</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Jeremy</span> <span class="surname">Allison</span></h3><div class="affiliation"><span class="orgname">Samba Team<br></span><div class="address"><p><br>
<tt class="email"><<a href="mailto:samba@samba.org">samba@samba.org</a>></tt><br>
</p></div></div></div></div><div><p class="pubdate">19 Apr 1999</p></div></div><div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><a href="#id2880380">Introduction</a></dt><dt><a href="#id2880405">How does it work?</a></dt><dt><a href="#id2880513">The smbpasswd file</a></dt></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2880380"></a>Introduction</h2></div></div><div></div></div><p>With the development of LanManager and Windows NT
compatible password encryption for Samba, it is now able
to validate user connections in exactly the same way as
a LanManager or Windows NT server.</p><p>This document describes how the SMB password encryption
algorithm works and what issues there are in choosing whether
you want to use it. You should read it carefully, especially
the part about security and the "PROS and CONS" section.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2880405"></a>How does it work?</h2></div></div><div></div></div><p>LanManager encryption is somewhat similar to UNIX
password encryption. The server uses a file containing a
hashed value of a user's password. This is created by taking
the user's plaintext password, capitalising it, and either
truncating to 14 bytes or padding to 14 bytes with null bytes.
This 14 byte value is used as two 56 bit DES keys to encrypt
a 'magic' eight byte value, forming a 16 byte value which is
stored by the server and client. Let this value be known as
the "hashed password".</p><p>Windows NT encryption is a higher quality mechanism,
consisting of doing an MD4 hash on a Unicode version of the user's
password. This also produces a 16 byte hash value that is
non-reversible.</p><p>When a client (LanManager, Windows for WorkGroups, Windows
95 or Windows NT) wishes to mount a Samba drive (or use a Samba
resource), it first requests a connection and negotiates the
protocol that the client and server will use. In the reply to this
request the Samba server generates and appends an 8 byte, random
value - this is stored in the Samba server after the reply is sent
and is known as the "challenge". The challenge is different for
every client connection.</p><p>The client then uses the hashed password (16 byte values
described above), appended with 5 null bytes, as three 56 bit
DES keys, each of which is used to encrypt the challenge 8 byte
value, forming a 24 byte value known as the "response".</p><p>In the SMB call SMBsessionsetupX (when user level security
is selected) or the call SMBtconX (when share level security is
selected), the 24 byte response is returned by the client to the
Samba server. For Windows NT protocol levels the above calculation
is done on both hashes of the user's password and both responses are
returned in the SMB call, giving two 24 byte values.</p><p>The Samba server then reproduces the above calculation, using
its own stored value of the 16 byte hashed password (read from the
<tt class="filename">smbpasswd</tt> file - described later) and the challenge
value that it kept from the negotiate protocol reply. It then checks
to see if the 24 byte value it calculates matches the 24 byte value
returned to it from the client.</p><p>If these values match exactly, then the client knew the
correct password (or the 16 byte hashed value - see security note
below) and is thus allowed access. If not, then the client did not
know the correct password and is denied access.</p><p>Note that the Samba server never knows or stores the cleartext
of the user's password - just the 16 byte hashed values derived from
it. Also note that the cleartext password or 16 byte hashed values
are never transmitted over the network - thus increasing security.</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2880513"></a>The smbpasswd file</h2></div></div><div></div></div><a name="SMBPASSWDFILEFORMAT"></a><p>In order for Samba to participate in the above protocol
it must be able to look up the 16 byte hashed values given a user name.
Unfortunately, as the UNIX password value is also a one way hash
function (ie. it is impossible to retrieve the cleartext of the user's
password given the UNIX hash of it), a separate password file
containing this 16 byte value must be kept. To minimise problems with
these two password files, getting out of sync, the UNIX <tt class="filename">
/etc/passwd</tt> and the <tt class="filename">smbpasswd</tt> file,
a utility, <b class="command">mksmbpasswd.sh</b>, is provided to generate
a smbpasswd file from a UNIX <tt class="filename">/etc/passwd</tt> file.
</p><p>To generate the smbpasswd file from your <tt class="filename">/etc/passwd
</tt> file use the following command:</p><p><tt class="prompt">$ </tt><b class="userinput"><tt>cat /etc/passwd | mksmbpasswd.sh
> /usr/local/samba/private/smbpasswd</tt></b></p><p>If you are running on a system that uses NIS, use</p><p><tt class="prompt">$ </tt><b class="userinput"><tt>ypcat passwd | mksmbpasswd.sh
> /usr/local/samba/private/smbpasswd</tt></b></p><p>The <b class="command">mksmbpasswd.sh</b> program is found in
the Samba source directory. By default, the smbpasswd file is
stored in :</p><p><tt class="filename">/usr/local/samba/private/smbpasswd</tt></p><p>The owner of the <tt class="filename">/usr/local/samba/private/</tt>
directory should be set to root, and the permissions on it should
be set to 0500 (<b class="command">chmod 500 /usr/local/samba/private</b>).
</p><p>Likewise, the smbpasswd file inside the private directory should
be owned by root and the permissions on is should be set to 0600
(<b class="command">chmod 600 smbpasswd</b>).</p><p>The format of the smbpasswd file is (The line has been
wrapped here. It should appear as one entry per line in
your smbpasswd file.)</p><pre class="programlisting">
username:uid:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:
[Account type]:LCT-<last-change-time>:Long name
</pre><p>Although only the <i class="replaceable"><tt>username</tt></i>,
<i class="replaceable"><tt>uid</tt></i>, <i class="replaceable"><tt>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</tt></i>,
[<i class="replaceable"><tt>Account type</tt></i>] and <i class="replaceable"><tt>
last-change-time</tt></i> sections are significant
and are looked at in the Samba code.</p><p>It is <span class="emphasis"><em>VITALLY</em></span> important that there by 32
'X' characters between the two ':' characters in the XXX sections -
the smbpasswd and Samba code will fail to validate any entries that
do not have 32 characters between ':' characters. The first XXX
section is for the Lanman password hash, the second is for the
Windows NT version.</p><p>When the password file is created all users have password entries
consisting of 32 'X' characters. By default this disallows any access
as this user. When a user has a password set, the 'X' characters change
to 32 ascii hexadecimal digits (0-9, A-F). These are an ascii
representation of the 16 byte hashed value of a user's password.</p><p>To set a user to have no password (not recommended), edit the file
using vi, and replace the first 11 characters with the ascii text
<tt class="constant">"NO PASSWORD"</tt> (minus the quotes).</p><p>For example, to clear the password for user bob, his smbpasswd file
entry would look like :</p><pre class="programlisting">
bob:100:NO PASSWORDXXXXXXXXXXXXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:
[U ]:LCT-00000000:Bob's full name:/bobhome:/bobshell
</pre><p>If you are allowing users to use the smbpasswd command to set
their own passwords, you may want to give users NO PASSWORD initially
so they do not have to enter a previous password when changing to their
new password (not recommended). In order for you to allow this the
<b class="command">smbpasswd</b> program must be able to connect to the
<b class="command">smbd</b> daemon as that user with no password. Enable this
by adding the line :</p><p><b class="command">null passwords = yes</b></p><p>to the [global] section of the smb.conf file (this is why
the above scenario is not recommended). Preferably, allocate your
users a default password to begin with, so you do not have
to enable this on your server.</p><p><span class="emphasis"><em>Note : </em></span>This file should be protected very
carefully. Anyone with access to this file can (with enough knowledge of
the protocols) gain access to your SMB server. The file is thus more
sensitive than a normal unix <tt class="filename">/etc/passwd</tt> file.</p></div></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="modules"></a>Chapter 15. Modules</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Jelmer</span> <span class="surname">Vernooij</span></h3><div class="affiliation"><span class="orgname">Samba Team<br></span><div class="address"><p><tt class="email"><<a href="mailto:jelmer@samba.org">jelmer@samba.org</a>></tt></p></div></div></div></div><div><p class="pubdate"> 19 March 2003 </p></div></div><div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><a href="#id2880880">Advantages</a></dt><dt><a href="#id2880927">Loading modules</a></dt><dd><dl><dt><a href="#id2880961">Static modules</a></dt><dt><a href="#id2881001">Shared modules</a></dt></dl></dd><dt><a href="#id2881029">Writing modules</a></dt><dd><dl><dt><a href="#id2881090">Static/Shared selection in configure.in</a></dt></dl></dd></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2880880"></a>Advantages</h2></div></div><div></div></div><p>
The new modules system has the following advantages:
</p><table class="simplelist" border="0" summary="Simple list"><tr><td>Transparent loading of static and shared modules (no need
for a subsystem to know about modules)</td></tr><tr><td>Simple selection between shared and static modules at configure time</td></tr><tr><td>"preload modules" option for increasing performance for stable modules</td></tr><tr><td>No nasty #define stuff anymore</td></tr><tr><td>All backends are available as plugin now (including pdb_ldap and pdb_tdb)</td></tr></table></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2880927"></a>Loading modules</h2></div></div><div></div></div><p>
Some subsystems in samba use different backends. These backends can be
either statically linked in to samba or available as a plugin. A subsystem
should have a function that allows a module to register itself. For example,
the passdb subsystem has:
</p><pre class="programlisting">
NTSTATUS smb_register_passdb(int version, const char *name, pdb_init_function init);
</pre><p>
This function will be called by the initialisation function of the module to
register itself.
</p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2880961"></a>Static modules</h3></div></div><div></div></div><p>
The modules system compiles a list of initialisation functions for the
static modules of each subsystem. This is a define. For example,
it is here currently (from <tt class="filename">include/config.h</tt>):
</p><pre class="programlisting">
/* Static init functions */
#define static_init_pdb { pdb_mysql_init(); pdb_ldap_init(); pdb_smbpasswd_init(); pdb_tdbsam_init(); pdb_guest_init();}
</pre><p>
These functions should be called before the subsystem is used. That
should be done when the subsystem is initialised or first used.
</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2881001"></a>Shared modules</h3></div></div><div></div></div><p>
If a subsystem needs a certain backend, it should check if it has
already been registered. If the backend hasn't been registered already,
the subsystem should call smb_probe_module(char *subsystem, char *backend).
This function tries to load the correct module from a certain path
($LIBDIR/subsystem/backend.so). If the first character in 'backend'
is a slash, smb_probe_module() tries to load the module from the
absolute path specified in 'backend'.
</p><p>After smb_probe_module() has been executed, the subsystem
should check again if the module has been registered.
</p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2881029"></a>Writing modules</h2></div></div><div></div></div><p>
Each module has an initialisation function. For modules that are
included with samba this name is '<i class="replaceable"><tt>subsystem</tt></i>_<i class="replaceable"><tt>backend</tt></i>_init'. For external modules (that will never be built-in, but only available as a module) this name is always 'init_module'. (In the case of modules included with samba, the configure system will add a #define subsystem_backend_init() init_module()).
The prototype for these functions is:
</p><pre class="programlisting">
NTSTATUS init_module(void);
</pre><p>This function should call one or more
registration functions. The function should return NT_STATUS_OK on success and
NT_STATUS_UNSUCCESSFUL or a more useful nt error code on failure.</p><p>For example, pdb_ldap_init() contains: </p><pre class="programlisting">
NTSTATUS pdb_ldap_init(void)
{
smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam", pdb_init_ldapsam);
smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam_nua", pdb_init_ldapsam_nua);
return NT_STATUS_OK;
}
</pre><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2881090"></a>Static/Shared selection in configure.in</h3></div></div><div></div></div><p>
Some macros in configure.in generate the various defines and substs that
are necessary for the system to work correct. All modules that should
be built by default have to be added to the variable 'default_modules'.
For example, if ldap is found, pdb_ldap is added to this variable.
</p><p>
On the bottom of configure.in, SMB_MODULE() should be called
for each module and SMB_SUBSYSTEM() for each subsystem.
</p><p>Syntax:</p><pre class="programlisting">
SMB_MODULE(<i class="replaceable"><tt>subsystem</tt></i>_<i class="replaceable"><tt>backend</tt></i>, <i class="replaceable"><tt>object files</tt></i>, <i class="replaceable"><tt>plugin name</tt></i>, <i class="replaceable"><tt>subsystem name</tt></i>, <i class="replaceable"><tt>static_action</tt></i>, <i class="replaceable"><tt>shared_action</tt></i>)
SMB_SUBSYSTEM(<i class="replaceable"><tt>subsystem</tt></i>,<i class="replaceable"><tt>depfile</tt></i>)
</pre><p>The depfile for a certain subsystem is the file that calls the
initialisation functions for the statically built in modules.</p><p>
<i class="replaceable"><tt>@SUBSYSTEM_MODULES@</tt></i> in Makefile.in will
be replaced with the names of the plugins to build.
</p><p>You must make sure all .c files that contain defines that can
be changed by ./configure are rebuilded in the 'modules_clean' make target.
Practically, this means all c files that contain <b class="command">static_init_subsystem;</b> calls need to be rebuilded.
</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
There currently also is a configure.in command called SMB_MODULE_PROVIVES().
This is used for modules that register multiple things. It should not
be used as probing will most likely disappear in the future.</p></div></div></div></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="rpc-plugin"></a>Chapter 16. RPC Pluggable Modules</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Anthony</span> <span class="surname">Liguori</span></h3><div class="affiliation"><span class="orgname">IBM<br></span><div class="address"><p><tt class="email"><<a href="mailto:aliguor@us.ibm.com">aliguor@us.ibm.com</a>></tt></p></div></div></div></div><div><div class="author"><h3 class="author"><span class="firstname">Jelmer</span> <span class="surname">Vernooij</span></h3><div class="affiliation"><span class="orgname">Samba Team<br></span><div class="address"><p><tt class="email"><<a href="mailto:jelmer@samba.org">jelmer@samba.org</a>></tt></p></div></div></div></div><div><p class="pubdate">January 2003</p></div></div><div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><a href="#id2881286">About</a></dt><dt><a href="#id2881305">General Overview</a></dt></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2881286"></a>About</h2></div></div><div></div></div><p>
This document describes how to make use the new RPC Pluggable Modules features
of Samba 3.0. This architecture was added to increase the maintainability of
Samba allowing RPC Pipes to be worked on separately from the main CVS branch.
The RPM architecture will also allow third-party vendors to add functionality
to Samba through plug-ins.
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2881305"></a>General Overview</h2></div></div><div></div></div><p>
When an RPC call is sent to smbd, smbd tries to load a shared library by the
name <tt class="filename">librpc_<pipename>.so</tt> to handle the call if
it doesn't know how to handle the call internally. For instance, LSA calls
are handled by <tt class="filename">librpc_lsass.so</tt>..
These shared libraries should be located in the <tt class="filename"><sambaroot>/lib/rpc</tt>. smbd then attempts to call the init_module function within
the shared library. Check the chapter on modules for more information.
</p><p>
In the init_module function, the library should call
rpc_pipe_register_commands(). This function takes the following arguments:
</p><pre class="programlisting">
NTSTATUS rpc_pipe_register_commands(int version, const char *clnt, const char *srv,
const struct api_struct *cmds, int size);
</pre><div class="variablelist"><dl><dt><span class="term">version</span></dt><dd><p>Version number of the RPC interface. Use the define <span class="emphasis"><em>SMB_RPC_INTERFACE_VERSION</em></span> for this
argument.</p></dd><dt><span class="term">clnt</span></dt><dd><p>the Client name of the named pipe</p></dd><dt><span class="term">srv</span></dt><dd><p>the Server name of the named pipe</p></dd><dt><span class="term">cmds</span></dt><dd><p>a list of api_structs that map RPC ordinal numbers to function calls</p></dd><dt><span class="term">size</span></dt><dd><p>the number of api_structs contained in cmds</p></dd></dl></div><p>
See rpc_server/srv_reg.c and rpc_server/srv_reg_nt.c for a small example of
how to use this library.
</p></div></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="vfs"></a>Chapter 17. VFS Modules</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Alexander</span> <span class="surname">Bokovoy</span></h3><div class="affiliation"><div class="address"><p><tt class="email"><<a href="mailto:ab@samba.org">ab@samba.org</a>></tt></p></div></div></div></div><div><div class="author"><h3 class="author"><span class="firstname">Stefan</span> <span class="surname">Metzmacher</span></h3><div class="affiliation"><div class="address"><p><tt class="email"><<a href="mailto:metze@metzemix.de">metze@metzemix.de</a>></tt></p></div></div></div></div><div><p class="pubdate"> 27 May 2003 </p></div></div><div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><a href="#id2881513">The Samba (Posix) VFS layer</a></dt><dd><dl><dt><a href="#id2881520">The general interface</a></dt><dt><a href="#id2881636">Possible VFS operation layers</a></dt></dl></dd><dt><a href="#id2881708">The Interaction between the Samba VFS subsystem and the modules</a></dt><dd><dl><dt><a href="#id2881715">Initialization and registration</a></dt><dt><a href="#id2881898">How the Modules handle per connection data</a></dt></dl></dd><dt><a href="#id2882143">Upgrading to the New VFS Interface</a></dt><dd><dl><dt><a href="#id2882150">Upgrading from 2.2.* and 3.0aplha modules</a></dt></dl></dd><dt><a href="#id2882641">Some Notes</a></dt><dd><dl><dt><a href="#id2882648">Implement TRANSPARENT functions</a></dt><dt><a href="#id2882674">Implement OPAQUE functions</a></dt></dl></dd></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2881513"></a>The Samba (Posix) VFS layer</h2></div></div><div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2881520"></a>The general interface</h3></div></div><div></div></div><p>
Each VFS operation has a vfs_op_type, a function pointer and a handle pointer in the
struct vfs_ops and tree macros to make it easier to call the operations.
(Take a look at <tt class="filename">include/vfs.h</tt> and <tt class="filename">include/vfs_macros.h</tt>.)
</p><pre class="programlisting">
typedef enum _vfs_op_type {
SMB_VFS_OP_NOOP = -1,
...
/* File operations */
SMB_VFS_OP_OPEN,
SMB_VFS_OP_CLOSE,
SMB_VFS_OP_READ,
SMB_VFS_OP_WRITE,
SMB_VFS_OP_LSEEK,
SMB_VFS_OP_SENDFILE,
...
SMB_VFS_OP_LAST
} vfs_op_type;
</pre><p>This struct contains the function and handle pointers for all operations.</p><pre class="programlisting">
struct vfs_ops {
struct vfs_fn_pointers {
...
/* File operations */
int (*open)(struct vfs_handle_struct *handle,
struct connection_struct *conn,
const char *fname, int flags, mode_t mode);
int (*close)(struct vfs_handle_struct *handle,
struct files_struct *fsp, int fd);
ssize_t (*read)(struct vfs_handle_struct *handle,
struct files_struct *fsp, int fd, void *data, size_t n);
ssize_t (*write)(struct vfs_handle_struct *handle,
struct files_struct *fsp, int fd,
const void *data, size_t n);
SMB_OFF_T (*lseek)(struct vfs_handle_struct *handle,
struct files_struct *fsp, int fd,
SMB_OFF_T offset, int whence);
ssize_t (*sendfile)(struct vfs_handle_struct *handle,
int tofd, files_struct *fsp, int fromfd,
const DATA_BLOB *header, SMB_OFF_T offset, size_t count);
...
} ops;
struct vfs_handles_pointers {
...
/* File operations */
struct vfs_handle_struct *open;
struct vfs_handle_struct *close;
struct vfs_handle_struct *read;
struct vfs_handle_struct *write;
struct vfs_handle_struct *lseek;
struct vfs_handle_struct *sendfile;
...
} handles;
};
</pre><p>
This macros SHOULD be used to call any vfs operation.
DO NOT ACCESS conn->vfs.ops.* directly !!!
</p><pre class="programlisting">
...
/* File operations */
#define SMB_VFS_OPEN(conn, fname, flags, mode) \
((conn)->vfs.ops.open((conn)->vfs.handles.open,\
(conn), (fname), (flags), (mode)))
#define SMB_VFS_CLOSE(fsp, fd) \
((fsp)->conn->vfs.ops.close(\
(fsp)->conn->vfs.handles.close, (fsp), (fd)))
#define SMB_VFS_READ(fsp, fd, data, n) \
((fsp)->conn->vfs.ops.read(\
(fsp)->conn->vfs.handles.read,\
(fsp), (fd), (data), (n)))
#define SMB_VFS_WRITE(fsp, fd, data, n) \
((fsp)->conn->vfs.ops.write(\
(fsp)->conn->vfs.handles.write,\
(fsp), (fd), (data), (n)))
#define SMB_VFS_LSEEK(fsp, fd, offset, whence) \
((fsp)->conn->vfs.ops.lseek(\
(fsp)->conn->vfs.handles.lseek,\
(fsp), (fd), (offset), (whence)))
#define SMB_VFS_SENDFILE(tofd, fsp, fromfd, header, offset, count) \
((fsp)->conn->vfs.ops.sendfile(\
(fsp)->conn->vfs.handles.sendfile,\
(tofd), (fsp), (fromfd), (header), (offset), (count)))
...
</pre></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2881636"></a>Possible VFS operation layers</h3></div></div><div></div></div><p>
These values are used by the VFS subsystem when building the conn->vfs
and conn->vfs_opaque structs for a connection with multiple VFS modules.
Internally, Samba differentiates only opaque and transparent layers at this process.
Other types are used for providing better diagnosing facilities.
</p><p>
Most modules will provide transparent layers. Opaque layer is for modules
which implement actual file system calls (like DB-based VFS). For example,
default POSIX VFS which is built in into Samba is an opaque VFS module.
</p><p>
Other layer types (logger, splitter, scanner) were designed to provide different
degree of transparency and for diagnosing VFS module behaviour.
</p><p>
Each module can implement several layers at the same time provided that only
one layer is used per each operation.
</p><pre class="programlisting">
typedef enum _vfs_op_layer {
SMB_VFS_LAYER_NOOP = -1, /* - For using in VFS module to indicate end of array */
/* of operations description */
SMB_VFS_LAYER_OPAQUE = 0, /* - Final level, does not call anything beyond itself */
SMB_VFS_LAYER_TRANSPARENT, /* - Normal operation, calls underlying layer after */
/* possibly changing passed data */
SMB_VFS_LAYER_LOGGER, /* - Logs data, calls underlying layer, logging may not */
/* use Samba VFS */
SMB_VFS_LAYER_SPLITTER, /* - Splits operation, calls underlying layer _and_ own facility, */
/* then combines result */
SMB_VFS_LAYER_SCANNER /* - Checks data and possibly initiates additional */
/* file activity like logging to files _inside_ samba VFS */
} vfs_op_layer;
</pre></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2881708"></a>The Interaction between the Samba VFS subsystem and the modules</h2></div></div><div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2881715"></a>Initialization and registration</h3></div></div><div></div></div><p>
As each Samba module a VFS module should have a
</p><pre class="programlisting">NTSTATUS vfs_example_init(void);</pre><p> function if it's staticly linked to samba or
</p><pre class="programlisting">NTSTATUS init_module(void);</pre><p> function if it's a shared module.
</p><p>
This should be the only non static function inside the module.
Global variables should also be static!
</p><p>
The module should register its functions via the
</p><pre class="programlisting">
NTSTATUS smb_register_vfs(int version, const char *name, vfs_op_tuple *vfs_op_tuples);
</pre><p> function.
</p><div class="variablelist"><dl><dt><span class="term">version</span></dt><dd><p>should be filled with SMB_VFS_INTERFACE_VERSION</p></dd><dt><span class="term">name</span></dt><dd><p>this is the name witch can be listed in the
<b class="command">vfs objects</b> parameter to use this module.</p></dd><dt><span class="term">vfs_op_tuples</span></dt><dd><p>
this is an array of vfs_op_tuple's.
(vfs_op_tuples is descripted in details below.)
</p></dd></dl></div><p>
For each operation the module wants to provide it has a entry in the
vfs_op_tuple array.
</p><pre class="programlisting">
typedef struct _vfs_op_tuple {
void* op;
vfs_op_type type;
vfs_op_layer layer;
} vfs_op_tuple;
</pre><div class="variablelist"><dl><dt><span class="term">op</span></dt><dd><p>the function pointer to the specified function.</p></dd><dt><span class="term">type</span></dt><dd><p>the vfs_op_type of the function to specified witch operation the function provides.</p></dd><dt><span class="term">layer</span></dt><dd><p>the vfs_op_layer in whitch the function operates.</p></dd></dl></div><p>A simple example:</p><pre class="programlisting">
static vfs_op_tuple example_op_tuples[] = {
{SMB_VFS_OP(example_connect), SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(example_disconnect), SMB_VFS_OP_DISCONNECT, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(example_rename), SMB_VFS_OP_RENAME, SMB_VFS_LAYER_OPAQUE},
/* This indicates the end of the array */
{SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
};
NTSTATUS init_module(void)
{
return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "example", example_op_tuples);
}
</pre></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2881898"></a>How the Modules handle per connection data</h3></div></div><div></div></div><p>Each VFS function has as first parameter a pointer to the modules vfs_handle_struct.
</p><pre class="programlisting">
typedef struct vfs_handle_struct {
struct vfs_handle_struct *next, *prev;
const char *param;
struct vfs_ops vfs_next;
struct connection_struct *conn;
void *data;
void (*free_data)(void **data);
} vfs_handle_struct;
</pre><div class="variablelist"><dl><dt><span class="term">param</span></dt><dd><p>this is the module parameter specified in the <b class="command">vfs objects</b> parameter.</p><p>e.g. for 'vfs objects = example:test' param would be "test".</p></dd><dt><span class="term">vfs_next</span></dt><dd><p>This vfs_ops struct contains the information for calling the next module operations.
Use the SMB_VFS_NEXT_* macros to call a next module operations and
don't access handle->vfs_next.ops.* directly!</p></dd><dt><span class="term">conn</span></dt><dd><p>This is a pointer back to the connection_struct to witch the handle belongs.</p></dd><dt><span class="term">data</span></dt><dd><p>This is a pointer for holding module private data.
You can alloc data with connection life time on the handle->conn->mem_ctx TALLOC_CTX.
But you can also manage the memory allocation yourself.</p></dd><dt><span class="term">free_data</span></dt><dd><p>This is a function pointer to a function that free's the module private data.
If you talloc your private data on the TALLOC_CTX handle->conn->mem_ctx,
you can set this function pointer to NULL.</p></dd></dl></div><p>Some useful MACROS for handle private data.
</p><pre class="programlisting">
#define SMB_VFS_HANDLE_GET_DATA(handle, datap, type, ret) { \
if (!(handle)||((datap=(type *)(handle)->data)==NULL)) { \
DEBUG(0,("%s() failed to get vfs_handle->data!\n",FUNCTION_MACRO)); \
ret; \
} \
}
#define SMB_VFS_HANDLE_SET_DATA(handle, datap, free_fn, type, ret) { \
if (!(handle)) { \
DEBUG(0,("%s() failed to set handle->data!\n",FUNCTION_MACRO)); \
ret; \
} else { \
if ((handle)->free_data) { \
(handle)->free_data(&(handle)->data); \
} \
(handle)->data = (void *)datap; \
(handle)->free_data = free_fn; \
} \
}
#define SMB_VFS_HANDLE_FREE_DATA(handle) { \
if ((handle) && (handle)->free_data) { \
(handle)->free_data(&(handle)->data); \
} \
}
</pre><p>How SMB_VFS_LAYER_TRANSPARENT functions can call the SMB_VFS_LAYER_OPAQUE functions.</p><p>The easiest way to do this is to use the SMB_VFS_OPAQUE_* macros.
</p><pre class="programlisting">
...
/* File operations */
#define SMB_VFS_OPAQUE_OPEN(conn, fname, flags, mode) \
((conn)->vfs_opaque.ops.open(\
(conn)->vfs_opaque.handles.open,\
(conn), (fname), (flags), (mode)))
#define SMB_VFS_OPAQUE_CLOSE(fsp, fd) \
((fsp)->conn->vfs_opaque.ops.close(\
(fsp)->conn->vfs_opaque.handles.close,\
(fsp), (fd)))
#define SMB_VFS_OPAQUE_READ(fsp, fd, data, n) \
((fsp)->conn->vfs_opaque.ops.read(\
(fsp)->conn->vfs_opaque.handles.read,\
(fsp), (fd), (data), (n)))
#define SMB_VFS_OPAQUE_WRITE(fsp, fd, data, n) \
((fsp)->conn->vfs_opaque.ops.write(\
(fsp)->conn->vfs_opaque.handles.write,\
(fsp), (fd), (data), (n)))
#define SMB_VFS_OPAQUE_LSEEK(fsp, fd, offset, whence) \
((fsp)->conn->vfs_opaque.ops.lseek(\
(fsp)->conn->vfs_opaque.handles.lseek,\
(fsp), (fd), (offset), (whence)))
#define SMB_VFS_OPAQUE_SENDFILE(tofd, fsp, fromfd, header, offset, count) \
((fsp)->conn->vfs_opaque.ops.sendfile(\
(fsp)->conn->vfs_opaque.handles.sendfile,\
(tofd), (fsp), (fromfd), (header), (offset), (count)))
...
</pre><p>How SMB_VFS_LAYER_TRANSPARENT functions can call the next modules functions.</p><p>The easiest way to do this is to use the SMB_VFS_NEXT_* macros.
</p><pre class="programlisting">
...
/* File operations */
#define SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode) \
((handle)->vfs_next.ops.open(\
(handle)->vfs_next.handles.open,\
(conn), (fname), (flags), (mode)))
#define SMB_VFS_NEXT_CLOSE(handle, fsp, fd) \
((handle)->vfs_next.ops.close(\
(handle)->vfs_next.handles.close,\
(fsp), (fd)))
#define SMB_VFS_NEXT_READ(handle, fsp, fd, data, n) \
((handle)->vfs_next.ops.read(\
(handle)->vfs_next.handles.read,\
(fsp), (fd), (data), (n)))
#define SMB_VFS_NEXT_WRITE(handle, fsp, fd, data, n) \
((handle)->vfs_next.ops.write(\
(handle)->vfs_next.handles.write,\
(fsp), (fd), (data), (n)))
#define SMB_VFS_NEXT_LSEEK(handle, fsp, fd, offset, whence) \
((handle)->vfs_next.ops.lseek(\
(handle)->vfs_next.handles.lseek,\
(fsp), (fd), (offset), (whence)))
#define SMB_VFS_NEXT_SENDFILE(handle, tofd, fsp, fromfd, header, offset, count) \
((handle)->vfs_next.ops.sendfile(\
(handle)->vfs_next.handles.sendfile,\
(tofd), (fsp), (fromfd), (header), (offset), (count)))
...
</pre></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2882143"></a>Upgrading to the New VFS Interface</h2></div></div><div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2882150"></a>Upgrading from 2.2.* and 3.0aplha modules</h3></div></div><div></div></div><div class="orderedlist"><ol type="1"><li><p>
Add "vfs_handle_struct *handle, " as first parameter to all vfs operation functions.
e.g. example_connect(connection_struct *conn, const char *service, const char *user);
-> example_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user);
</p></li><li><p>
Replace "default_vfs_ops." with "smb_vfs_next_".
e.g. default_vfs_ops.connect(conn, service, user);
-> smb_vfs_next_connect(conn, service, user);
</p></li><li><p>
Uppercase all "smb_vfs_next_*" functions.
e.g. smb_vfs_next_connect(conn, service, user);
-> SMB_VFS_NEXT_CONNECT(conn, service, user);
</p></li><li><p>
Add "handle, " as first parameter to all SMB_VFS_NEXT_*() calls.
e.g. SMB_VFS_NEXT_CONNECT(conn, service, user);
-> SMB_VFS_NEXT_CONNECT(handle, conn, service, user);
</p></li><li><p>
(Only for 2.2.* modules)
Convert the old struct vfs_ops example_ops to
a vfs_op_tuple example_op_tuples[] array.
e.g.
</p><pre class="programlisting">
struct vfs_ops example_ops = {
/* Disk operations */
example_connect, /* connect */
example_disconnect, /* disconnect */
NULL, /* disk free *
/* Directory operations */
NULL, /* opendir */
NULL, /* readdir */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* closedir */
/* File operations */
NULL, /* open */
NULL, /* close */
NULL, /* read */
NULL, /* write */
NULL, /* lseek */
NULL, /* sendfile */
NULL, /* rename */
NULL, /* fsync */
example_stat, /* stat */
example_fstat, /* fstat */
example_lstat, /* lstat */
NULL, /* unlink */
NULL, /* chmod */
NULL, /* fchmod */
NULL, /* chown */
NULL, /* fchown */
NULL, /* chdir */
NULL, /* getwd */
NULL, /* utime */
NULL, /* ftruncate */
NULL, /* lock */
NULL, /* symlink */
NULL, /* readlink */
NULL, /* link */
NULL, /* mknod */
NULL, /* realpath */
NULL, /* fget_nt_acl */
NULL, /* get_nt_acl */
NULL, /* fset_nt_acl */
NULL, /* set_nt_acl */
NULL, /* chmod_acl */
NULL, /* fchmod_acl */
NULL, /* sys_acl_get_entry */
NULL, /* sys_acl_get_tag_type */
NULL, /* sys_acl_get_permset */
NULL, /* sys_acl_get_qualifier */
NULL, /* sys_acl_get_file */
NULL, /* sys_acl_get_fd */
NULL, /* sys_acl_clear_perms */
NULL, /* sys_acl_add_perm */
NULL, /* sys_acl_to_text */
NULL, /* sys_acl_init */
NULL, /* sys_acl_create_entry */
NULL, /* sys_acl_set_tag_type */
NULL, /* sys_acl_set_qualifier */
NULL, /* sys_acl_set_permset */
NULL, /* sys_acl_valid */
NULL, /* sys_acl_set_file */
NULL, /* sys_acl_set_fd */
NULL, /* sys_acl_delete_def_file */
NULL, /* sys_acl_get_perm */
NULL, /* sys_acl_free_text */
NULL, /* sys_acl_free_acl */
NULL /* sys_acl_free_qualifier */
};
</pre><p>
->
</p><pre class="programlisting">
static vfs_op_tuple example_op_tuples[] = {
{SMB_VFS_OP(example_connect), SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(example_disconnect), SMB_VFS_OP_DISCONNECT, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(example_fstat), SMB_VFS_OP_FSTAT, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(example_stat), SMB_VFS_OP_STAT, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(example_lstat), SMB_VFS_OP_LSTAT, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
};
</pre><p>
</p></li><li><p>
Move the example_op_tuples[] array to the end of the file.
</p></li><li><p>
Add the init_module() function at the end of the file.
e.g.
</p><pre class="programlisting">
NTSTATUS init_module(void)
{
return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,"example",example_op_tuples);
}
</pre><p>
</p></li><li><p>
Check if your vfs_init() function does more then just prepare the vfs_ops structs or
remember the struct smb_vfs_handle_struct.
</p><table class="simplelist" border="0" summary="Simple list"><tr><td>If NOT you can remove the vfs_init() function.</td></tr><tr><td>If YES decide if you want to move the code to the example_connect() operation or to the init_module(). And then remove vfs_init().
e.g. a debug class registration should go into init_module() and the allocation of private data should go to example_connect().</td></tr></table><p>
</p></li><li><p>
(Only for 3.0alpha* modules)
Check if your vfs_done() function contains needed code.
</p><table class="simplelist" border="0" summary="Simple list"><tr><td>If NOT you can remove the vfs_done() function.</td></tr><tr><td>If YES decide if you can move the code to the example_disconnect() operation. Otherwise register a SMB_EXIT_EVENT with smb_register_exit_event(); (Described in the <link linkend="modules">) And then remove vfs_done(). e.g. the freeing of private data should go to example_disconnect().
</td></tr></table><p>
</p></li><li><p>
Check if you have any global variables left.
Decide if it wouldn't be better to have this data on a connection basis.
</p><table class="simplelist" border="0" summary="Simple list"><tr><td>If NOT leave them as they are. (e.g. this could be the variable for the private debug class.)</td></tr><tr><td>If YES pack all this data into a struct. You can use handle->data to point to such a struct on a per connection basis.</td></tr></table><p>
e.g. if you have such a struct:
</p><pre class="programlisting">
struct example_privates {
char *some_string;
int db_connection;
};
</pre><p>
first way of doing it:
</p><pre class="programlisting">
static int example_connect(vfs_handle_struct *handle,
connection_struct *conn, const char *service,
const char* user)
{
struct example_privates *data = NULL;
/* alloc our private data */
data = (struct example_privates *)talloc_zero(conn->mem_ctx, sizeof(struct example_privates));
if (!data) {
DEBUG(0,("talloc_zero() failed\n"));
return -1;
}
/* init out private data */
data->some_string = talloc_strdup(conn->mem_ctx,"test");
if (!data->some_string) {
DEBUG(0,("talloc_strdup() failed\n"));
return -1;
}
data->db_connection = open_db_conn();
/* and now store the private data pointer in handle->data
* we don't need to specify a free_function here because
* we use the connection TALLOC context.
* (return -1 if something failed.)
*/
VFS_HANDLE_SET_DATA(handle, data, NULL, struct example_privates, return -1);
return SMB_VFS_NEXT_CONNECT(handle,conn,service,user);
}
static int example_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
{
struct example_privates *data = NULL;
/* get the pointer to our private data
* return -1 if something failed
*/
SMB_VFS_HANDLE_GET_DATA(handle, data, struct example_privates, return -1);
/* do something here...*/
DEBUG(0,("some_string: %s\n",data->some_string));
return SMB_VFS_NEXT_CLOSE(handle, fsp, fd);
}
</pre><p>
second way of doing it:
</p><pre class="programlisting">
static void free_example_privates(void **datap)
{
struct example_privates *data = (struct example_privates *)*datap;
SAFE_FREE(data->some_string);
SAFE_FREE(data);
*datap = NULL;
return;
}
static int example_connect(vfs_handle_struct *handle,
connection_struct *conn, const char *service,
const char* user)
{
struct example_privates *data = NULL;
/* alloc our private data */
data = (struct example_privates *)malloc(sizeof(struct example_privates));
if (!data) {
DEBUG(0,("malloc() failed\n"));
return -1;
}
/* init out private data */
data->some_string = strdup("test");
if (!data->some_string) {
DEBUG(0,("strdup() failed\n"));
return -1;
}
data->db_connection = open_db_conn();
/* and now store the private data pointer in handle->data
* we need to specify a free_function because we used malloc() and strdup().
* (return -1 if something failed.)
*/
SMB_VFS_HANDLE_SET_DATA(handle, data, free_example_privates, struct example_privates, return -1);
return SMB_VFS_NEXT_CONNECT(handle,conn,service,user);
}
static int example_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
{
struct example_privates *data = NULL;
/* get the pointer to our private data
* return -1 if something failed
*/
SMB_VFS_HANDLE_GET_DATA(handle, data, struct example_privates, return -1);
/* do something here...*/
DEBUG(0,("some_string: %s\n",data->some_string));
return SMB_VFS_NEXT_CLOSE(handle, fsp, fd);
}
</pre><p>
</p></li><li><p>
To make it easy to build 3rd party modules it would be usefull to provide
configure.in, (configure), install.sh and Makefile.in with the module.
(Take a look at the example in <tt class="filename">examples/VFS</tt>.)
</p><p>
The configure script accepts <tt class="option">--with-samba-source</tt> to specify
the path to the samba source tree.
It also accept <tt class="option">--enable-developer</tt> which lets the compiler
give you more warnings.
</p><p>
The idea is that you can extend this
<tt class="filename">configure.in</tt> and <tt class="filename">Makefile.in</tt> scripts
for your module.
</p></li><li><p>
Compiling & Testing...
</p><table class="simplelist" border="0" summary="Simple list"><tr><td><b class="userinput"><tt>./configure <tt class="option">--enable-developer</tt></tt></b> ...</td></tr><tr><td><b class="userinput"><tt>make</tt></b></td></tr><tr><td>Try to fix all compiler warnings</td></tr><tr><td><b class="userinput"><tt>make</tt></b></td></tr><tr><td>Testing, Testing, Testing ...</td></tr></table><p>
</p></li></ol></div></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2882641"></a>Some Notes</h2></div></div><div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2882648"></a>Implement TRANSPARENT functions</h3></div></div><div></div></div><p>
Avoid writing functions like this:
</p><pre class="programlisting">
static int example_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
{
return SMB_VFS_NEXT_CLOSE(handle, fsp, fd);
}
</pre><p>
Overload only the functions you really need to!
</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2882674"></a>Implement OPAQUE functions</h3></div></div><div></div></div><p>
If you want to just implement a better version of a
default samba opaque function
(e.g. like a disk_free() function for a special filesystem)
it's ok to just overload that specific function.
</p><p>
If you want to implement a database filesystem or
something different from a posix filesystem.
Make sure that you overload every vfs operation!!!
</p><p>
Functions your FS does not support should be overloaded by something like this:
e.g. for a readonly filesystem.
</p><pre class="programlisting">
static int example_rename(vfs_handle_struct *handle, connection_struct *conn,
char *oldname, char *newname)
{
DEBUG(10,("function rename() not allowed on vfs 'example'\n"));
errno = ENOSYS;
return -1;
}
</pre></div></div></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="Packaging"></a>Chapter 18. Notes to packagers</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Jelmer</span> <span class="surname">Vernooij</span></h3></div></div></div><div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><a href="#id2882741">Versioning</a></dt><dt><a href="#id2882774">Modules</a></dt></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2882741"></a>Versioning</h2></div></div><div></div></div><p>Please, please update the version number in
<tt class="filename">source/include/version.h</tt> to include the versioning of your package. This makes it easier to distinguish standard samba builds
from custom-build samba builds (distributions often patch packages). For
example, a good version would be: </p><pre class="programlisting">
Version 2.999+3.0.alpha21-5 for Debian
</pre></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2882774"></a>Modules</h2></div></div><div></div></div><p>Samba now has support for building parts of samba as plugins. This
makes it possible to, for example, put ldap or mysql support in a seperate
package, thus making it possible to have a normal samba package not
depending on ldap or mysql. To build as much parts of samba
as a plugin, run: </p><pre class="programlisting">
./configure --with-shared-modules=rpc,vfs,auth,pdb,charset
</pre></div></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="contributing"></a>Chapter 19. Contributing code</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Jelmer</span> <span class="othername">R.</span> <span class="surname">Vernooij</span></h3><div class="affiliation"><span class="orgname">The Samba Team<br></span><div class="address"><p><tt class="email"><<a href="mailto:jelmer@samba.org">jelmer@samba.org</a>></tt></p></div></div></div></div></div><div></div></div><p>Here are a few tips and notes that might be useful if you are
interested in modifying samba source code and getting it into
samba's main branch.</p><div class="variablelist"><dl><dt><span class="term">Retrieving the source</span></dt><dd><p>In order to contribute code to samba, make sure you have the
latest source. Retrieving the samba source code from CVS is
documented in the appendix of the Samba HOWTO Collection.
</p></dd><dt><span class="term">Discuss large modifications with team members</span></dt><dd><p>Please discuss large modifications you are going to make
with members of the samba team. Some parts of the samba code
have one or more 'owners' - samba developers who wrote most
of the code and maintain it.
</p><p>This way you can avoid spending your time and effort on
something that is not going to make it into the main samba branch
because someone else was working on the same thing or because your
implementation is not the correct one.
</p></dd><dt><span class="term">Patch format</span></dt><dd><p>Patches to the samba tree should be in unified diff format,
e.g. files generated by <b class="userinput"><tt>diff -u</tt></b>.
</p><p>If you are modifying a copy of samba you retrieved from CVS,
you can easily generate a diff file of these changes by running
<b class="userinput"><tt>cvs diff -u</tt></b>.</p></dd><dt><span class="term">Points of attention when modifying samba source code</span></dt><dd><p>
</p><table class="simplelist" border="0" summary="Simple list"><tr><td>Don't simply copy code from other places and modify it until it
works. Code needs to be clean and logical. Duplicate
code is to be avoided.</td></tr><tr><td>Test your patch. It might take a while before one of us looks
at your patch so it will take longer before your patch when your patch
needs to go thru the review cycle again.</td></tr><tr><td>Don't put seperate patches in one large diff file. This makes
it harder to read, understand and test the patch. You might
also risk not getting a good patch committed because you mixed it
with one that had issues. </td></tr><tr><td>Make sure your patch complies to the samba coding style as
suggested in the coding-suggestions chapter. </td></tr></table><p>
</p></dd><dt><span class="term">Sending in bugfixes</span></dt><dd><p>Bugfixes to bugs in samba should be submitted to samba's
<ulink url="https://bugzilla.samba.org/">bugzilla system</ulink>,
along with a description of the bug.
</p></dd><dt><span class="term">Sending in feature patches</span></dt><dd><p>Send feature patches along with a description of what the
patch is supposed to do to the
<ulink url="mailto:samba-technical@samba.org">Samba-technical mailinglist</ulink> and possibly to a samba team member who is (one of the) 'owners'
of the code you made modifications to. We are all busy people
so everybody tends to 'let one of the others handle it'. If nobody
responded to your patch for a week, try to send it again until you
get a response from one of us.
</p></dd><dt><span class="term">Feedback on your patch</span></dt><dd><p>One of the team members will look at your patch and either
commit your patch or give comments why he won't apply it. In the
latter case you can fix your patch and re-send it until
your patch is approved.</p></dd></dl></div></div></div></body></html>
|