1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package waffle.util;
25
26 import com.sun.jna.Platform;
27 import com.sun.jna.platform.WindowUtils;
28 import com.sun.jna.platform.win32.LMJoin;
29 import com.sun.jna.platform.win32.Netapi32Util;
30 import com.sun.jna.platform.win32.Win32Exception;
31
32 import java.awt.Desktop;
33 import java.io.File;
34 import java.io.IOException;
35 import java.io.StringWriter;
36 import java.nio.charset.StandardCharsets;
37 import java.nio.file.Files;
38 import java.nio.file.StandardOpenOption;
39 import java.util.ArrayList;
40 import java.util.Arrays;
41 import java.util.List;
42
43 import javax.xml.XMLConstants;
44 import javax.xml.parsers.DocumentBuilderFactory;
45 import javax.xml.parsers.ParserConfigurationException;
46 import javax.xml.transform.OutputKeys;
47 import javax.xml.transform.Transformer;
48 import javax.xml.transform.TransformerException;
49 import javax.xml.transform.TransformerFactory;
50 import javax.xml.transform.dom.DOMSource;
51 import javax.xml.transform.stream.StreamResult;
52
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55 import org.w3c.dom.Document;
56 import org.w3c.dom.Element;
57
58 import waffle.windows.auth.IWindowsAccount;
59 import waffle.windows.auth.IWindowsAuthProvider;
60 import waffle.windows.auth.IWindowsComputer;
61 import waffle.windows.auth.IWindowsDomain;
62 import waffle.windows.auth.impl.WindowsAccountImpl;
63 import waffle.windows.auth.impl.WindowsAuthProviderImpl;
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 public class WaffleInfo {
97
98
99 private static final Logger LOGGER = LoggerFactory.getLogger(WaffleInfo.class);
100
101
102
103
104
105
106
107
108
109
110
111 public Document getWaffleInfo() throws ParserConfigurationException {
112 final DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
113 df.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
114 df.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
115 df.setExpandEntityReferences(false);
116
117 final Document doc = df.newDocumentBuilder().newDocument();
118
119
120 final Element root = doc.createElement("waffle");
121
122
123 String version = WaffleInfo.class.getPackage().getImplementationVersion();
124 if (version != null) {
125 root.setAttribute("version", version);
126 }
127 version = Platform.class.getPackage().getImplementationVersion();
128 if (version != null) {
129 root.setAttribute("jna", version);
130 }
131 version = WindowUtils.class.getPackage().getImplementationVersion();
132 if (version != null) {
133 root.setAttribute("jna-platform", version);
134 }
135
136 doc.appendChild(root);
137 root.appendChild(this.getAuthProviderInfo(doc));
138
139 return doc;
140 }
141
142
143
144
145
146
147
148
149
150 protected Element getAuthProviderInfo(final Document doc) {
151 final IWindowsAuthProvider auth = new WindowsAuthProviderImpl();
152
153 final Element node = doc.createElement("auth");
154 node.setAttribute("class", auth.getClass().getName());
155
156
157 Element child = doc.createElement("currentUser");
158 node.appendChild(child);
159
160 final String currentUsername = WindowsAccountImpl.getCurrentUsername();
161 this.addAccountInfo(doc, child, new WindowsAccountImpl(currentUsername));
162
163
164 child = doc.createElement("computer");
165 node.appendChild(child);
166
167 final IWindowsComputer c = auth.getCurrentComputer();
168 Element value = doc.createElement("computerName");
169 value.setTextContent(c.getComputerName());
170 child.appendChild(value);
171
172 value = doc.createElement("memberOf");
173 value.setTextContent(c.getMemberOf());
174 child.appendChild(value);
175
176 value = doc.createElement("joinStatus");
177 value.setTextContent(c.getJoinStatus());
178 child.appendChild(value);
179
180 value = doc.createElement("groups");
181 Element g;
182 for (final String s : c.getGroups()) {
183 g = doc.createElement("group");
184 g.setTextContent(s);
185 value.appendChild(g);
186 }
187 child.appendChild(value);
188
189
190 if (Netapi32Util.getJoinStatus() == LMJoin.NETSETUP_JOIN_STATUS.NetSetupDomainName) {
191 child = doc.createElement("domains");
192 node.appendChild(child);
193
194 Element d;
195 for (final IWindowsDomain domain : auth.getDomains()) {
196 d = doc.createElement("domain");
197 node.appendChild(d);
198
199 value = doc.createElement("FQN");
200 value.setTextContent(domain.getFqn());
201 child.appendChild(value);
202
203 value = doc.createElement("TrustTypeString");
204 value.setTextContent(domain.getTrustTypeString());
205 child.appendChild(value);
206
207 value = doc.createElement("TrustDirectionString");
208 value.setTextContent(domain.getTrustDirectionString());
209 child.appendChild(value);
210 }
211 }
212 return node;
213 }
214
215
216
217
218
219
220
221
222
223
224
225 protected void addAccountInfo(final Document doc, final Element node, final IWindowsAccount account) {
226 Element value = doc.createElement("Name");
227 value.setTextContent(account.getName());
228 node.appendChild(value);
229
230 value = doc.createElement("FQN");
231 value.setTextContent(account.getFqn());
232 node.appendChild(value);
233
234 value = doc.createElement("Domain");
235 value.setTextContent(account.getDomain());
236 node.appendChild(value);
237
238 value = doc.createElement("SID");
239 value.setTextContent(account.getSidString());
240 node.appendChild(value);
241 }
242
243
244
245
246
247
248
249
250
251
252
253 public Element getLookupInfo(final Document doc, final String lookup) {
254 final IWindowsAuthProvider auth = new WindowsAuthProviderImpl();
255 final Element node = doc.createElement("lookup");
256 node.setAttribute("name", lookup);
257 try {
258 this.addAccountInfo(doc, node, auth.lookupAccount(lookup));
259 } catch (final Win32Exception e) {
260 node.appendChild(WaffleInfo.getException(doc, e));
261 }
262 return node;
263 }
264
265
266
267
268
269
270
271
272
273
274
275 public static Element getException(final Document doc, final Exception t) {
276 final Element node = doc.createElement("exception");
277 node.setAttribute("class", t.getClass().getName());
278
279 Element value = doc.createElement("message");
280 if (t.getMessage() != null) {
281 value.setTextContent(t.getMessage());
282 node.appendChild(value);
283 }
284
285 value = doc.createElement("trace");
286 value.setTextContent(Arrays.toString(t.getStackTrace()));
287 node.appendChild(value);
288 return node;
289 }
290
291
292
293
294
295
296
297
298
299
300
301
302 public static String toPrettyXML(final Document doc) throws TransformerException {
303
304 final TransformerFactory transfac = TransformerFactory.newInstance();
305 transfac.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
306 transfac.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
307
308 final Transformer trans = transfac.newTransformer();
309 trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
310 trans.setOutputProperty(OutputKeys.INDENT, "yes");
311
312
313 final StringWriter sw = new StringWriter();
314 final StreamResult result = new StreamResult(sw);
315 final DOMSource source = new DOMSource(doc);
316 trans.transform(source, result);
317 return sw.toString();
318 }
319
320
321
322
323
324
325
326 public static void main(final String[] args) {
327 boolean show = false;
328 final List<String> lookup = new ArrayList<>();
329 if (args != null) {
330 String arg;
331 for (int i = 0; i < args.length; i++) {
332 arg = args[i];
333 if (null != arg) {
334 switch (arg) {
335 case "-show":
336 show = true;
337 break;
338 case "-lookup":
339 lookup.add(args[++i]);
340 break;
341 default:
342 WaffleInfo.LOGGER.error("Unknown Argument: {}", arg);
343 throw new RuntimeException("Unknown Argument: " + arg);
344 }
345 }
346 }
347 }
348
349 final WaffleInfo helper = new WaffleInfo();
350 try {
351 final Document info = helper.getWaffleInfo();
352 for (final String name : lookup) {
353 info.getDocumentElement().appendChild(helper.getLookupInfo(info, name));
354 }
355
356 final String xml = WaffleInfo.toPrettyXML(info);
357 final File f;
358 if (show) {
359 f = Files.createTempFile("waffle-info-", ".xml").toFile();
360 Files.write(f.toPath(), xml.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
361 Desktop.getDesktop().open(f);
362 } else {
363 WaffleInfo.LOGGER.info(xml);
364 }
365 } catch (final IOException | TransformerException | ParserConfigurationException e) {
366 WaffleInfo.LOGGER.error(e.getMessage());
367 WaffleInfo.LOGGER.trace("", e);
368 }
369 }
370 }