/lsass/interop/dsplugin/macadutil/netinfo.c

https://github.com/BeyondTrust/pbis-open · C · 570 lines · 429 code · 83 blank · 58 comment · 119 complexity · 86a18c9ab2be7f5745afca6c20d5bbdb MD5 · raw file

  1. /* Editor Settings: expandtabs and use 4 spaces for indentation
  2. * ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: *
  3. * -*- mode: c, c-basic-offset: 4 -*- */
  4. /*
  5. * Copyright © BeyondTrust Software 2004 - 2019
  6. * All rights reserved.
  7. *
  8. * Licensed under the Apache License, Version 2.0 (the "License");
  9. * you may not use this file except in compliance with the License.
  10. * You may obtain a copy of the License at
  11. *
  12. * http://www.apache.org/licenses/LICENSE-2.0
  13. *
  14. * Unless required by applicable law or agreed to in writing, software
  15. * distributed under the License is distributed on an "AS IS" BASIS,
  16. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. *
  20. * BEYONDTRUST MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING TERMS AS
  21. * WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT WITH
  22. * BEYONDTRUST, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE TERMS OF THAT
  23. * SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE APACHE LICENSE,
  24. * NOTWITHSTANDING THE ABOVE NOTICE. IF YOU HAVE QUESTIONS, OR WISH TO REQUEST
  25. * A COPY OF THE ALTERNATE LICENSING TERMS OFFERED BY BEYONDTRUST, PLEASE CONTACT
  26. * BEYONDTRUST AT beyondtrust.com/contact
  27. */
  28. #include "../includes.h"
  29. static const DWORD BUFSIZE = 4096;
  30. static
  31. DWORD
  32. GetEthernetAddress(
  33. PSTR pszAdapterName,
  34. PSTR * ppszENetAddress
  35. );
  36. static
  37. DWORD
  38. GetIPAddress(
  39. PSTR pszAdapterName,
  40. PSTR * ppszIPAddress
  41. );
  42. static
  43. BOOLEAN
  44. GetIsRunning(
  45. PSTR pszAdapterName
  46. );
  47. static
  48. BOOLEAN
  49. GetIsUp(
  50. PSTR pszAdapterName
  51. );
  52. DWORD
  53. LWGetNetAdapterList(
  54. BOOLEAN fEnXOnly,
  55. PNETADAPTERINFO * ppNetAdapterList
  56. )
  57. {
  58. DWORD dwError = 0;
  59. char szCommand[PATH_MAX + 1];
  60. FILE * pFile = NULL;
  61. char szBuf[BUFSIZE+1];
  62. pid_t child = 0;
  63. int filedes[2] = {-1, -1};
  64. PNETADAPTERINFO pAdapterList = NULL;
  65. PNETADAPTERINFO pPrev = NULL;
  66. PNETADAPTERINFO pNew = NULL;
  67. BOOLEAN IsEthernet = FALSE;
  68. if (!ppNetAdapterList) {
  69. dwError = MAC_AD_ERROR_INVALID_PARAMETER;
  70. BAIL_ON_MAC_ERROR(dwError);
  71. }
  72. sprintf(szCommand,
  73. "/sbin/ifconfig -a | grep \"flags\" | awk '{print $1}'");
  74. /* popen fails for some reason here on Solaris. Instead we
  75. emulate it. */
  76. if (pipe(filedes) != 0)
  77. {
  78. dwError = errno;
  79. BAIL_ON_MAC_ERROR(dwError);
  80. }
  81. child = fork();
  82. if(child == (pid_t)-1)
  83. {
  84. dwError = errno;
  85. BAIL_ON_MAC_ERROR(dwError);
  86. }
  87. if(child == 0)
  88. {
  89. /* The child */
  90. close(filedes[0]);
  91. dup2(filedes[1], 1);
  92. close(filedes[1]);
  93. execl("/bin/sh", "sh", "-c", szCommand, (char *)0);
  94. /* This exit call should not be reached */
  95. exit(-1);
  96. }
  97. /* The parent */
  98. close(filedes[1]);
  99. filedes[1] = -1;
  100. pFile = fdopen(filedes[0], "r");
  101. if (pFile == NULL) {
  102. dwError = errno;
  103. BAIL_ON_MAC_ERROR(dwError);
  104. }
  105. /* pFile now owns the descriptor */
  106. filedes[0] = -1;
  107. while (!feof(pFile)) {
  108. IsEthernet = FALSE;
  109. if (NULL != fgets(szBuf, BUFSIZE, pFile)) {
  110. LwStripWhitespace(szBuf, TRUE, TRUE);
  111. if (strlen(szBuf) > 2) {
  112. if (szBuf[strlen(szBuf) - 1] == ':')
  113. szBuf[strlen(szBuf) - 1] = 0;
  114. if (szBuf[0] == 'e' && szBuf[1] == 'n')
  115. IsEthernet = TRUE;
  116. } else {
  117. /* This adapter name does not seem proper, skip to next line of output */
  118. continue;
  119. }
  120. if ( (fEnXOnly && IsEthernet) || (!fEnXOnly) ) {
  121. dwError = LwAllocateMemory(sizeof(NETADAPTERINFO), (PVOID*) &pNew);
  122. BAIL_ON_MAC_ERROR(dwError);
  123. dwError = LwAllocateString(szBuf, &pNew->pszName);
  124. BAIL_ON_MAC_ERROR(dwError);
  125. GetEthernetAddress(pNew->pszName, &pNew->pszENetAddress);
  126. GetIPAddress(pNew->pszName, &pNew->pszIPAddress);
  127. pNew->IsUp = GetIsUp(pNew->pszName);
  128. pNew->IsRunning = GetIsRunning(pNew->pszName);
  129. if (pAdapterList) {
  130. pPrev->pNext = pNew;
  131. pPrev = pNew;
  132. } else {
  133. pAdapterList = pNew;
  134. pPrev = pAdapterList;
  135. }
  136. pNew = NULL;
  137. }
  138. }
  139. }
  140. if (pAdapterList) {
  141. *ppNetAdapterList = pAdapterList;
  142. pAdapterList = NULL;
  143. }
  144. cleanup:
  145. if (pFile != NULL) {
  146. pclose(pFile);
  147. }
  148. if (filedes[0] != -1)
  149. close(filedes[0]);
  150. if (filedes[1] != -1)
  151. close(filedes[1]);
  152. if (child != 0)
  153. {
  154. int status;
  155. waitpid(child, &status, 0);
  156. }
  157. if (pAdapterList)
  158. LWFreeNetAdapterList(pAdapterList);
  159. if (pNew)
  160. LWFreeNetAdapterList(pNew);
  161. return dwError;
  162. error:
  163. goto cleanup;
  164. }
  165. void
  166. LWFreeNetAdapterList(
  167. PNETADAPTERINFO pNetAdapterList
  168. )
  169. {
  170. while (pNetAdapterList)
  171. {
  172. PNETADAPTERINFO pTemp = pNetAdapterList;
  173. pNetAdapterList = pNetAdapterList->pNext;
  174. LW_SAFE_FREE_STRING(pTemp->pszName);
  175. LW_SAFE_FREE_STRING(pTemp->pszENetAddress);
  176. LW_SAFE_FREE_STRING(pTemp->pszIPAddress);
  177. LwFreeMemory(pTemp);
  178. }
  179. }
  180. static
  181. DWORD
  182. GetEthernetAddress(
  183. PSTR pszAdapterName,
  184. PSTR * ppszENetAddress
  185. )
  186. {
  187. DWORD dwError = 0;
  188. char szCommand[PATH_MAX + 1];
  189. FILE * pFile = NULL;
  190. char szBuf[BUFSIZE+1];
  191. pid_t child = 0;
  192. int filedes[2] = {-1, -1};
  193. if (!pszAdapterName || !ppszENetAddress) {
  194. dwError = eParameterError;
  195. BAIL_ON_MAC_ERROR(dwError);
  196. }
  197. sprintf(szCommand,
  198. "/sbin/ifconfig %s | grep \"ether \" | awk '{print $2}'",
  199. pszAdapterName);
  200. /* popen fails for some reason here on Solaris. Instead we
  201. emulate it. */
  202. if (pipe(filedes) != 0)
  203. {
  204. dwError = errno;
  205. BAIL_ON_MAC_ERROR(dwError);
  206. }
  207. child = fork();
  208. if(child == (pid_t)-1)
  209. {
  210. dwError = errno;
  211. BAIL_ON_MAC_ERROR(dwError);
  212. }
  213. if(child == 0)
  214. {
  215. /* The child */
  216. close(filedes[0]);
  217. dup2(filedes[1], 1);
  218. close(filedes[1]);
  219. execl("/bin/sh", "sh", "-c", szCommand, (char *)0);
  220. /* This exit call should not be reached */
  221. exit(-1);
  222. }
  223. /* The parent */
  224. close(filedes[1]);
  225. filedes[1] = -1;
  226. pFile = fdopen(filedes[0], "r");
  227. if (pFile == NULL) {
  228. dwError = errno;
  229. BAIL_ON_MAC_ERROR(dwError);
  230. }
  231. /* pFile now owns the descriptor */
  232. filedes[0] = -1;
  233. if (!feof(pFile) && (NULL != fgets(szBuf, BUFSIZE, pFile))) {
  234. LwStripWhitespace(szBuf, TRUE, TRUE);
  235. dwError = LwAllocateString(szBuf, ppszENetAddress);
  236. BAIL_ON_MAC_ERROR(dwError);
  237. }
  238. else
  239. {
  240. dwError = MAC_AD_ERROR_NO_SUCH_ATTRIBUTE;
  241. BAIL_ON_MAC_ERROR(dwError);
  242. }
  243. cleanup:
  244. if (pFile != NULL) {
  245. pclose(pFile);
  246. }
  247. if (filedes[0] != -1)
  248. close(filedes[0]);
  249. if (filedes[1] != -1)
  250. close(filedes[1]);
  251. if (child != 0)
  252. {
  253. int status;
  254. waitpid(child, &status, 0);
  255. }
  256. return dwError;
  257. error:
  258. goto cleanup;
  259. }
  260. static
  261. DWORD
  262. GetIPAddress(
  263. PSTR pszAdapterName,
  264. PSTR * ppszIPAddress
  265. )
  266. {
  267. DWORD dwError = 0;
  268. char szCommand[PATH_MAX + 1];
  269. FILE * pFile = NULL;
  270. char szBuf[BUFSIZE+1];
  271. pid_t child = 0;
  272. int filedes[2] = {-1, -1};
  273. if (!pszAdapterName || !ppszIPAddress) {
  274. dwError = eParameterError;
  275. BAIL_ON_MAC_ERROR(dwError);
  276. }
  277. sprintf(szCommand,
  278. "/sbin/ifconfig %s | grep \"inet \" | awk '{print $2}'",
  279. pszAdapterName);
  280. /* popen fails for some reason here on Solaris. Instead we
  281. emulate it. */
  282. if (pipe(filedes) != 0)
  283. {
  284. dwError = errno;
  285. BAIL_ON_MAC_ERROR(dwError);
  286. }
  287. child = fork();
  288. if(child == (pid_t)-1)
  289. {
  290. dwError = errno;
  291. BAIL_ON_MAC_ERROR(dwError);
  292. }
  293. if(child == 0)
  294. {
  295. /* The child */
  296. close(filedes[0]);
  297. dup2(filedes[1], 1);
  298. close(filedes[1]);
  299. execl("/bin/sh", "sh", "-c", szCommand, (char *)0);
  300. /* This exit call should not be reached */
  301. exit(-1);
  302. }
  303. /* The parent */
  304. close(filedes[1]);
  305. filedes[1] = -1;
  306. pFile = fdopen(filedes[0], "r");
  307. if (pFile == NULL) {
  308. dwError = errno;
  309. BAIL_ON_MAC_ERROR(dwError);
  310. }
  311. /* pFile now owns the descriptor */
  312. filedes[0] = -1;
  313. if (!feof(pFile) && (NULL != fgets(szBuf, BUFSIZE, pFile))) {
  314. LwStripWhitespace(szBuf, TRUE, TRUE);
  315. dwError = LwAllocateString(szBuf, ppszIPAddress);
  316. BAIL_ON_MAC_ERROR(dwError);
  317. }
  318. else
  319. {
  320. dwError = MAC_AD_ERROR_NO_SUCH_ATTRIBUTE;
  321. BAIL_ON_MAC_ERROR(dwError);
  322. }
  323. cleanup:
  324. if (pFile != NULL) {
  325. pclose(pFile);
  326. }
  327. if (filedes[0] != -1)
  328. close(filedes[0]);
  329. if (filedes[1] != -1)
  330. close(filedes[1]);
  331. if (child != 0)
  332. {
  333. int status;
  334. waitpid(child, &status, 0);
  335. }
  336. return dwError;
  337. error:
  338. goto cleanup;
  339. }
  340. static
  341. BOOLEAN
  342. GetIsUp(
  343. PSTR pszAdapterName
  344. )
  345. {
  346. DWORD dwError = 0;
  347. char szCommand[PATH_MAX + 1];
  348. FILE * pFile = NULL;
  349. char szBuf[BUFSIZE+1];
  350. pid_t child = 0;
  351. int filedes[2] = {-1, -1};
  352. BOOLEAN fIsUp = FALSE;
  353. if (!pszAdapterName) {
  354. dwError = eParameterError;
  355. BAIL_ON_MAC_ERROR(dwError);
  356. }
  357. sprintf(szCommand,
  358. "/sbin/ifconfig %s | grep \"UP\"",
  359. pszAdapterName);
  360. /* popen fails for some reason here on Solaris. Instead we
  361. emulate it. */
  362. if (pipe(filedes) != 0)
  363. {
  364. dwError = errno;
  365. BAIL_ON_MAC_ERROR(dwError);
  366. }
  367. child = fork();
  368. if(child == (pid_t)-1)
  369. {
  370. dwError = errno;
  371. BAIL_ON_MAC_ERROR(dwError);
  372. }
  373. if(child == 0)
  374. {
  375. /* The child */
  376. close(filedes[0]);
  377. dup2(filedes[1], 1);
  378. close(filedes[1]);
  379. execl("/bin/sh", "sh", "-c", szCommand, (char *)0);
  380. /* This exit call should not be reached */
  381. exit(-1);
  382. }
  383. /* The parent */
  384. close(filedes[1]);
  385. filedes[1] = -1;
  386. pFile = fdopen(filedes[0], "r");
  387. if (pFile == NULL) {
  388. dwError = errno;
  389. BAIL_ON_MAC_ERROR(dwError);
  390. }
  391. /* pFile now owns the descriptor */
  392. filedes[0] = -1;
  393. if (!feof(pFile) && (NULL != fgets(szBuf, BUFSIZE, pFile))) {
  394. fIsUp = TRUE;
  395. }
  396. cleanup:
  397. if (pFile != NULL) {
  398. pclose(pFile);
  399. }
  400. if (filedes[0] != -1)
  401. close(filedes[0]);
  402. if (filedes[1] != -1)
  403. close(filedes[1]);
  404. if (child != 0)
  405. {
  406. int status;
  407. waitpid(child, &status, 0);
  408. }
  409. return fIsUp;
  410. error:
  411. fIsUp = FALSE;
  412. goto cleanup;
  413. }
  414. static
  415. BOOLEAN
  416. GetIsRunning(
  417. PSTR pszAdapterName
  418. )
  419. {
  420. DWORD dwError = 0;
  421. char szCommand[PATH_MAX + 1];
  422. FILE * pFile = NULL;
  423. char szBuf[BUFSIZE+1];
  424. pid_t child = 0;
  425. int filedes[2] = {-1, -1};
  426. BOOLEAN fIsRunning = FALSE;
  427. if (!pszAdapterName) {
  428. dwError = eParameterError;
  429. BAIL_ON_MAC_ERROR(dwError);
  430. }
  431. sprintf(szCommand,
  432. "/sbin/ifconfig %s | grep \"RUNNING\"",
  433. pszAdapterName);
  434. /* popen fails for some reason here on Solaris. Instead we
  435. emulate it. */
  436. if (pipe(filedes) != 0)
  437. {
  438. dwError = errno;
  439. BAIL_ON_MAC_ERROR(dwError);
  440. }
  441. child = fork();
  442. if(child == (pid_t)-1)
  443. {
  444. dwError = errno;
  445. BAIL_ON_MAC_ERROR(dwError);
  446. }
  447. if(child == 0)
  448. {
  449. /* The child */
  450. close(filedes[0]);
  451. dup2(filedes[1], 1);
  452. close(filedes[1]);
  453. execl("/bin/sh", "sh", "-c", szCommand, (char *)0);
  454. /* This exit call should not be reached */
  455. exit(-1);
  456. }
  457. /* The parent */
  458. close(filedes[1]);
  459. filedes[1] = -1;
  460. pFile = fdopen(filedes[0], "r");
  461. if (pFile == NULL) {
  462. dwError = errno;
  463. BAIL_ON_MAC_ERROR(dwError);
  464. }
  465. /* pFile now owns the descriptor */
  466. filedes[0] = -1;
  467. if (!feof(pFile) && (NULL != fgets(szBuf, BUFSIZE, pFile))) {
  468. fIsRunning = TRUE;
  469. }
  470. cleanup:
  471. if (pFile != NULL) {
  472. pclose(pFile);
  473. }
  474. if (filedes[0] != -1)
  475. close(filedes[0]);
  476. if (filedes[1] != -1)
  477. close(filedes[1]);
  478. if (child != 0)
  479. {
  480. int status;
  481. waitpid(child, &status, 0);
  482. }
  483. return fIsRunning;
  484. error:
  485. fIsRunning = FALSE;
  486. goto cleanup;
  487. }