bool keepbroad; /* keep broadcasting */
bool globalbroad; /* use global broadcast address (255.255.255.255) */
/* switch properties */
+ bool encrypt_pass; /* switch uses password "encryption" */
char password[PASSWORD_MAX]; /* password to use to login on switches */
struct swi_attr *swi_tab; /* array of detected switches */
int swi_count; /* number of detected switches */
int i, ret = ERR_OK;
unsigned char err;
unsigned short attr_error;
+ struct attr *at;
if (nga == NULL) {
attr = createEmptyList();
/* add password attribute to start */
- pushFrontList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
+ at = newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password));
+ if (nga->encrypt_pass)
+ passwordEndecode(at->data, at->size);
+ pushFrontList(attr, at);
/* add end attribute to end */
pushBackList(attr, newEmptyAttr(ATTR_END));
int ngadmin_login (struct ngadmin *nga, int id)
{
List *attr;
+ struct attr *at;
int ret = ERR_OK;
struct swi_attr *sa;
sa = &nga->swi_tab[id];
nga->current = sa;
+ nga->encrypt_pass = false;
attr = createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_ENCPASS));
+ ret = readRequest(nga, attr);
+ if (ret != ERR_OK)
+ goto end;
+
+ filterAttributes(attr, ATTR_ENCPASS, ATTR_END);
+ if (attr->first != NULL) {
+ at = attr->first->data;
+ nga->encrypt_pass = (at->size == 4 && ntohl(*(unsigned int*)at->data) == 1);
+ }
+ clearList(attr, (void(*)(void*))freeAttr);
+
+ /* Strangely, passwords must never be encrypted inside a read request,
+ * or it will be rejected. Seems more to be a firmware bug. */
pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
ret = readRequest(nga, attr);
if (ret == ERR_OK ) {
nga->current = NULL;
}
+end:
destroyList(attr, (void(*)(void*))freeAttr);
int ngadmin_changePassword (struct ngadmin *nga, const char* pass)
{
List *attr;
+ struct attr *at;
int ret = ERR_OK;
attr = createEmptyList();
- pushBackList(attr, newAttr(ATTR_NEW_PASSWORD, strlen(pass), strdup(pass)));
+ at = newAttr(ATTR_NEW_PASSWORD, strlen(pass), strdup(pass));
+ if (nga->encrypt_pass)
+ passwordEndecode(at->data, at->size);
+ pushBackList(attr, at);
ret = writeRequest(nga, attr);
if (ret != ERR_OK)
goto end;
#define ATTR_UNK_000F 0x000F
#define ATTR_FIRM_UPGRADE 0x0010
#define ATTR_RESTART 0x0013
+#define ATTR_ENCPASS 0x0014
#define ATTR_DEFAULTS 0x0400
#define ATTR_PORT_STATUS 0x0C00
#define ATTR_PORT_STATISTICS 0x1000
};
+extern const char passwordKey[];
+
+
+void passwordEndecode (char *buf, unsigned int len);
+
int trim (char *txt, int start);
ATTR_HANDLER_ENTRY(ATTR_GATEWAY, 4, NULL, NULL),
ATTR_HANDLER_ENTRY(ATTR_DHCP, 2, NULL, NULL),
ATTR_HANDLER_ENTRY(ATTR_RESTART, 1, NULL, NULL),
+ ATTR_HANDLER_ENTRY(ATTR_ENCPASS, 4, NULL, NULL),
ATTR_HANDLER_ENTRY(ATTR_DEFAULTS, 1, NULL, NULL),
ATTR_HANDLER_ENTRY(ATTR_PORT_STATUS, sizeof(struct attr_port_status), NULL, ports_status_decode),
ATTR_HANDLER_ENTRY(ATTR_PORT_STATISTICS, sizeof(struct attr_port_stat), NULL, port_stat_decode),
+const char passwordKey[] = "NtgrSmartSwitchRock";
+
+
+void passwordEndecode (char *buf, unsigned int len)
+{
+ const char *k = passwordKey;
+ unsigned int i;
+
+ if (buf == NULL || len <= 0)
+ return;
+
+ for (i = 0; i < len; i++) {
+ if (*k == '\0')
+ k = passwordKey;
+ buf[i] ^= *k++;
+ }
+}
+
+
int trim (char *txt, int start)
{
char *p;