Is this of any use for a new GPS driver? - Galaxy S I9000 General

Code:
drivers/misc/Kconfig | 11 +
drivers/misc/Makefile | 1 +
drivers/misc/bcm4751-gps.c | 490 +++++++++++++++++++++++++++++++++++++++
include/linux/i2c/bcm4751-gps.h | 59 +++++
4 files changed, 561 insertions(+), 0 deletions(-)
create mode 100644 drivers/misc/bcm4751-gps.c
create mode 100644 include/linux/i2c/bcm4751-gps.h
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 0b591b6..1680673 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -390,6 +390,17 @@ config BMP085
To compile this driver as a module, choose M here: the
module will be called bmp085.
+config BCM4751_GPS
+ tristate "BCM4751 GPS driver"
+ depends on I2C
+ default n
+ ---help---
+ If you say yes here you get support for the Broadcom BCM4751 GPS
+ chip driver.
+
+ The driver supports only GPS in BCM4751 chip. When built as a driver
+ driver name is: bcm4751-gps. If unsure, say N here.
+
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 255a80d..cfda6fb 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_AD525X_DPOT_SPI) += ad525x_dpot-spi.o
obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o
obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o
obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o
+obj-$(CONFIG_BCM4751_GPS) += bcm4751-gps.o
obj-$(CONFIG_BMP085) += bmp085.o
obj-$(CONFIG_ICS932S401) += ics932s401.o
obj-$(CONFIG_LKDTM) += lkdtm.o
diff --git a/drivers/misc/bcm4751-gps.c b/drivers/misc/bcm4751-gps.c
new file mode 100644
index 0000000..03a3752
--- /dev/null
+++ b/drivers/misc/bcm4751-gps.c
@@ -0,0 +1,490 @@
+/*
+ * bcm4751-gps.c - Hardware interface for Broadcom BCM4751 GPS chip.
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Contact Matti Aaltonen, [email protected]
+ *
+ * Written by Andrei Emeltchenko <[email protected]>
+ * Modified by Yuri Zaporozhets <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#define DEBUG
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/poll.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+#include <linux/i2c/bcm4751-gps.h>
+
+static struct bcm4751_gps_data *bcm4751_gps_device;
+
+static const char reg_vbat[] = "Vbat";
+static const char reg_vddio[] = "Vddio";
+
+/*
+ * Part of initialization is done in the board support file.
+ */
+
+static inline void bcm4751_gps_enable(struct bcm4751_gps_data *self)
+{
+ mutex_lock(&self->mutex);
+ if (!self->enable) {
+ regulator_bulk_enable(ARRAY_SIZE(self->regs), self->regs);
+ if (self->pdata->enable)
+ self->pdata->enable(self->client);
+ self->enable = 1;
+ }
+ mutex_unlock(&self->mutex);
+}
+
+static inline void bcm4751_gps_disable(struct bcm4751_gps_data *self)
+{
+ mutex_lock(&self->mutex);
+ if (self->enable) {
+ if (self->pdata->disable)
+ self->pdata->disable(self->client);
+ self->enable = 0;
+ regulator_bulk_disable(ARRAY_SIZE(self->regs), self->regs);
+ }
+ mutex_unlock(&self->mutex);
+}
+
+static inline void bcm4751_gps_wakeup_value(struct bcm4751_gps_data *self,
+ int value)
+{
+ mutex_lock(&self->mutex);
+ if (self->pdata->wakeup_ctrl)
+ self->pdata->wakeup_ctrl(self->client, value);
+ self->wakeup = value;
+ mutex_unlock(&self->mutex);
+}
+
+
+/*
+ * miscdevice interface
+ */
+
+static int bcm4751_gps_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int bcm4751_gps_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static ssize_t bcm4751_gps_read(struct file *file, char __user *buf,
+ size_t count, loff_t *offset)
+{
+ struct i2c_client *client = bcm4751_gps_device->client;
+ int num_read;
+ uint8_t tmp[BCM4751_MAX_BINPKT_RX_LEN];
+
+ /* Adjust for binary packet size */
+ if (count > BCM4751_MAX_BINPKT_RX_LEN)
+ count = BCM4751_MAX_BINPKT_RX_LEN;
+
+ dev_dbg(&client->dev, "reading %d bytes\n", count);
+
+ num_read = i2c_master_recv(client, tmp, count);
+
+ if (num_read < 0) {
+ dev_err(&client->dev, "got %d bytes instead of %d\n",
+ num_read, count);
+ return num_read;
+ } else {
+ dev_dbg(&client->dev, "reading %d bytes returns %d",
+ count, num_read);
+ }
+
+ return copy_to_user(buf, tmp, num_read) ? -EFAULT : num_read;
+}
+
+static ssize_t bcm4751_gps_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *offset)
+{
+ struct i2c_client *client = bcm4751_gps_device->client;
+ uint8_t tmp[BCM4751_MAX_BINPKT_TX_LEN];
+ int num_sent;
+
+ if (count > BCM4751_MAX_BINPKT_TX_LEN)
+ count = BCM4751_MAX_BINPKT_TX_LEN;
+
+ dev_dbg(&client->dev, "writing %d bytes\n", count);
+
+ if (copy_from_user(tmp, buf, count))
+ return -EFAULT;
+
+ num_sent = i2c_master_send(client, tmp, count);
+
+ dev_dbg(&client->dev, "writing %d bytes returns %d",
+ count, num_sent);
+
+ return num_sent;
+}
+
+static int bcm4751_gps_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct i2c_client *client = bcm4751_gps_device->client;
+
+ dev_dbg(&client->dev, "ioctl: cmd = 0x%02x, arg=0x%02lx\n", cmd, arg);
+
+ switch (cmd) {
+ case I2C_SLAVE:
+ case I2C_SLAVE_FORCE:
+ if ((arg > 0x3ff) ||
+ (((client->flags & I2C_M_TEN) == 0) &&
+ arg > 0x7f))
+ return -EINVAL;
+ client->addr = arg;
+ dev_dbg(&client->dev, "ioctl: client->addr = %x", client->addr);
+ return 0;
+ case I2C_TENBIT:
+ if (arg)
+ client->flags |= I2C_M_TEN;
+ else
+ client->flags &= ~I2C_M_TEN;
+ return 0;
+ default:
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+static const struct file_operations bcm4751_gps_fileops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .read = bcm4751_gps_read,
+ .write = bcm4751_gps_write,
+ .unlocked_ioctl = bcm4751_gps_ioctl,
+ .open = bcm4751_gps_open,
+ .release = bcm4751_gps_release,
+};
+
+static struct miscdevice bcm4751_gps_miscdevice = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "bcm4751-gps",
+ .fops = &bcm4751_gps_fileops
+};
+
+
+/*
+ * sysfs interface
+ */
+
+static ssize_t bcm4751_gps_show_hostreq(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct bcm4751_gps_data *self = dev_get_drvdata(dev);
+ int value = -1;
+
+ if (self->pdata->show_irq)
+ value = self->pdata->show_irq(self->client);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", value);
+}
+
+static ssize_t bcm4751_gps_show_enable(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct bcm4751_gps_data *self = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", self->enable);
+}
+
+static ssize_t bcm4751_gps_set_enable(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ struct bcm4751_gps_data *self = dev_get_drvdata(dev);
+ int value;
+
+ sscanf(buf, "%d", &value);
+ dev_dbg(dev, "enable: %d", value);
+
+ switch (value) {
+ case 0:
+ bcm4751_gps_disable(self);
+ break;
+
+ case 1:
+ bcm4751_gps_enable(self);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ return len;
+}
+
+static ssize_t bcm4751_gps_show_wakeup(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct bcm4751_gps_data *self = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", self->wakeup);
+}
+
+static ssize_t bcm4751_gps_set_wakeup(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ unsigned long val;
+ int ret;
+ struct bcm4751_gps_data *self = dev_get_drvdata(dev);
+
+ ret = strict_strtoul(buf, 0, &val);
+ if (ret && val > 1)
+ return -EINVAL;
+ else {
+ bcm4751_gps_wakeup_value(self, val);
+ dev_dbg(dev, "new wakeup value = %d", self->wakeup);
+ }
+
+ return len;
+}
+
+static struct device_attribute bcm4751_gps_attrs[] = {
+ __ATTR(enable, S_IRUGO|S_IWUSR,
+ bcm4751_gps_show_enable, bcm4751_gps_set_enable),
+ __ATTR(hostreq, S_IRUGO|S_IWUSR,
+ bcm4751_gps_show_hostreq, NULL),
+ __ATTR(wakeup, S_IRUGO|S_IWUSR,
+ bcm4751_gps_show_wakeup, bcm4751_gps_set_wakeup),
+};
+
+static int bcm4751_gps_register_sysfs(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(bcm4751_gps_attrs); i++) {
+ ret = device_create_file(dev, &bcm4751_gps_attrs[i]);
+ if (ret)
+ goto fail;
+ }
+ return 0;
+fail:
+ while (i--)
+ device_remove_file(dev, &bcm4751_gps_attrs[i]);
+
+ return ret;
+}
+
+static void bcm4751_gps_unregister_sysfs(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ int i;
+
+ for (i = ARRAY_SIZE(bcm4751_gps_attrs) - 1; i >= 0; i--)
+ device_remove_file(dev, &bcm4751_gps_attrs[i]);
+}
+
+/* IRQ thread */
+static irqreturn_t bcm4751_gps_irq_thread(int irq, void *dev_id)
+{
+ struct bcm4751_gps_data *data = dev_id;
+
+ dev_dbg(&data->client->dev, "irq, HOST_REQ=%d",
+ data->pdata->show_irq(data->client));
+
+ /* Update sysfs GPIO line here */
+ sysfs_notify(&data->client->dev.kobj, NULL, "hostreq");
+ return IRQ_HANDLED;
+}
+
+static int bcm4751_gps_probe(struct i2c_client *client,
+ const struct i2c_device_id *device_id)
+{
+ struct bcm4751_gps_data *data;
+ struct bcm4751_gps_platform_data *pdata;
+ int err;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ bcm4751_gps_device = data;
+
+ pdata = client->dev.platform_data;
+ if (!pdata) {
+ dev_err(&client->dev, "no platform data\n");
+ err = -ENODEV;
+ goto clean_data;
+ }
+
+ i2c_set_clientdata(client, data);
+ data->client = client;
+ data->pdata = pdata;
+
+ data->gpio_irq = pdata->gps_gpio_irq;
+ data->gpio_enable = pdata->gps_gpio_enable;
+ data->gpio_wakeup = pdata->gps_gpio_wakeup;
+
+ data->regs[0].supply = reg_vbat;
+ data->regs[1].supply = reg_vddio;
+ err = regulator_bulk_get(&client->dev,
+ ARRAY_SIZE(data->regs), data->regs);
+ if (err < 0) {
+ dev_err(&client->dev, "Can't get regulators\n");
+ goto clean_data;
+ }
+
+ if (pdata->setup) {
+ err = pdata->setup(client);
+ if (err)
+ goto clean_reg;
+ }
+
+ mutex_init(&data->mutex);
+ err = request_threaded_irq(client->irq, NULL,
+ bcm4751_gps_irq_thread,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ "bcm4751-gps", data);
+ if (err) {
+ dev_err(&client->dev, "could not get GPS_IRQ = %d\n",
+ client->irq);
+ goto clean_setup;
+ }
+
+ err = bcm4751_gps_register_sysfs(client);
+ if (err) {
+ dev_err(&client->dev,
+ "sysfs registration failed, error %d\n", err);
+ goto clean_irq;
+ }
+
+ bcm4751_gps_miscdevice.parent = &client->dev;
+ err = misc_register(&bcm4751_gps_miscdevice);
+ if (err) {
+ dev_err(&client->dev, "Miscdevice register failed\n");
+ goto clean_sysfs;
+ }
+
+ return 0;
+
+clean_sysfs:
+ bcm4751_gps_unregister_sysfs(client);
+
+clean_irq:
+ free_irq(client->irq, data);
+
+clean_setup:
+ if (pdata->cleanup)
+ pdata->cleanup(client);
+clean_reg:
+ regulator_bulk_free(ARRAY_SIZE(data->regs), data->regs);
+clean_data:
+ bcm4751_gps_device = NULL;
+ kfree(data);
+
+ return err;
+}
+
+static int bcm4751_gps_remove(struct i2c_client *client)
+{
+ struct bcm4751_gps_data *data = i2c_get_clientdata(client);
+
+ bcm4751_gps_disable(data);
+
+ free_irq(client->irq, data);
+ misc_deregister(&bcm4751_gps_miscdevice);
+ bcm4751_gps_unregister_sysfs(client);
+ if (data->pdata->cleanup)
+ data->pdata->cleanup(client);
+ regulator_bulk_free(ARRAY_SIZE(data->regs), data->regs);
+ kfree(data);
+ bcm4751_gps_device = NULL;
+
+ return 0;
+}
+
+static void bcm4751_gps_shutdown(struct i2c_client *client)
+{
+ dev_dbg(&client->dev, "BCM4751 shutdown\n");
+ bcm4751_gps_disable(i2c_get_clientdata(client));
+}
+
+#ifdef CONFIG_PM
+static int bcm4751_gps_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+ struct bcm4751_gps_data *data = i2c_get_clientdata(client);
+ data->pdata->wakeup_ctrl(data->client, 0);
+ dev_dbg(&client->dev, "BCM4751 suspends\n");
+ return 0;
+}
+
+static int bcm4751_gps_resume(struct i2c_client *client)
+{
+ struct bcm4751_gps_data *data = i2c_get_clientdata(client);
+ data->pdata->wakeup_ctrl(data->client, 1);
+ dev_dbg(&client->dev, "BCM4751 resumes\n");
+ return 0;
+}
+#else
+#define bcm4751_gps_suspend NULL
+#define bcm4751_gps_resume NULL
+#endif
+
+static const struct i2c_device_id bcm4751_gps_id[] = {
+ { "bcm4751-gps", 0 },
+ { },
+};
+
+MODULE_DEVICE_TABLE(i2c, bcm4751_gps_id);
+
+static struct i2c_driver bcm4751_gps_i2c_driver = {
+ .driver = {
+ .name = "bcm4751-gps",
+ },
+
+ .id_table = bcm4751_gps_id,
+ .probe = bcm4751_gps_probe,
+ .remove = __devexit_p(bcm4751_gps_remove),
+ .shutdown = bcm4751_gps_shutdown,
+ .suspend = bcm4751_gps_suspend,
+ .resume = bcm4751_gps_resume,
+};
+
+static int __init bcm4751_gps_init(void)
+{
+ pr_info("Loading BCM4751 GPS driver\n");
+
+ return i2c_add_driver(&bcm4751_gps_i2c_driver);
+}
+module_init(bcm4751_gps_init);
+
+static void __exit bcm4751_gps_exit(void)
+{
+ i2c_del_driver(&bcm4751_gps_i2c_driver);
+}
+module_exit(bcm4751_gps_exit);
+
+MODULE_AUTHOR("Andrei Emeltchenko, Yuri Zaporozhets");
+MODULE_DESCRIPTION("BCM4751 GPS driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/i2c/bcm4751-gps.h b/include/linux/i2c/bcm4751-gps.h
new file mode 100644
index 0000000..69834b9
--- /dev/null
+++ b/include/linux/i2c/bcm4751-gps.h
@@ -0,0 +1,59 @@
+/*
+ * @file include/linux/i2c/bcm4751-gps.h
+ *
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Contact Matti Aaltonen, [email protected]
+ *
+ * Written by Andrei Emeltchenko <[email protected]>
+ * Modified by Yuri Zaporozhets <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef _LINUX_I2C_BCM4751_GPS_H
+#define _LINUX_I2C_BCM4751_GPS_H
+
+/* Max packet sizes for RX and TX */
+#define BCM4751_MAX_BINPKT_RX_LEN 64
+#define BCM4751_MAX_BINPKT_TX_LEN 64
+
+/* Plaform data, used by the board support file */
+struct bcm4751_gps_platform_data {
+ int gps_gpio_irq;
+ int gps_gpio_enable;
+ int gps_gpio_wakeup;
+ int (*setup)(struct i2c_client *client);
+ void (*cleanup)(struct i2c_client *client);
+ void (*enable)(struct i2c_client *client);
+ void (*disable)(struct i2c_client *client);
+ void (*wakeup_ctrl)(struct i2c_client *client, int value);
+ int (*show_irq)(struct i2c_client *client);
+};
+
+/* Used internally by the driver */
+struct bcm4751_gps_data {
+ struct i2c_client *client;
+ struct bcm4751_gps_platform_data *pdata;
+ struct mutex mutex; /* Serialize things */
+ struct regulator_bulk_data regs[2];
+ unsigned int gpio_irq;
+ unsigned int gpio_enable;
+ unsigned int gpio_wakeup;
+ int enable;
+ int wakeup;
+};
+
+#endif
This is nokia's linux driver for the bcm4751 device. Can this be repackaged?

Related

Encryption algo in ba_dpodcht_12406_110_10600 + radio ROM

The most recent ROM update released by Dopod has changed the format of NBF files. Here is the information I've found. Maybe someone would create a new xda3nbftool from the code I provide? I don't have time for this. Probably the same format soon would be used in other operator's updates.
New NBF files header is normally 0xAB bytes in length and looks like "K7qAW73q39..skipped..t7=". It is a base64 encoded string with a modified alphabet. The string length may change in the newer version, so you need to search for "=" to find the end of a header.
Here is a sample code that decodes it:
Code:
/*
* $Id: base64.c,v 1.1.1.1 2001/10/04 00:16:06 andrewr Exp $
* modified by mamaich for HTC firmware
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static void base64_init(void);
static int base64_initialized = 0;
#define BASE64_VALUE_SZ 256
#define BASE64_RESULT_SZ 8192
int base64_value[BASE64_VALUE_SZ];
/*
* This is the original base64 decode table:
*
const char* base64_code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
*/
/*
* BaUpgradeUt uses a modified alphabet:
*/
const char* base64_code = "yz98765432UVWXYZabcdKLMNOPQRSTopqrstuvwxefghijklmnABCDEFGHIJ10+/";
static void
base64_init(void)
{
int i;
for (i = 0; i < BASE64_VALUE_SZ; i++)
base64_value[i] = -1;
for (i = 0; i < 64; i++)
base64_value[(int) base64_code[i]] = i;
base64_value['='] = 0;
base64_initialized = 1;
}
char *
base64_decode(const char *p)
{
static char result[BASE64_RESULT_SZ];
int j;
int c;
long val;
if (!p)
return NULL;
if (!base64_initialized)
base64_init();
val = c = 0;
for (j = 0; *p && j + 4 < BASE64_RESULT_SZ; p++) {
unsigned int k = ((unsigned char) *p) % BASE64_VALUE_SZ;
if (base64_value[k] < 0)
continue;
val <<= 6;
val += base64_value[k];
if (++c < 4)
continue;
/* One quantum of four encoding characters/24 bit */
result[j++] = val >> 16; /* High 8 bits */
result[j++] = (val >> 8) & 0xff; /* Mid 8 bits */
result[j++] = val & 0xff; /* Low 8 bits */
val = c = 0;
}
result[j] = 0;
return result;
}
/* adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments */
const char *
base64_encode(const char *decoded_str)
{
static char result[BASE64_RESULT_SZ];
int bits = 0;
int char_count = 0;
int out_cnt = 0;
int c;
if (!decoded_str)
return decoded_str;
if (!base64_initialized)
base64_init();
while ((c = (unsigned char) *decoded_str++) && out_cnt < sizeof(result) - 5) {
bits += c;
char_count++;
if (char_count == 3) {
result[out_cnt++] = base64_code[bits >> 18];
result[out_cnt++] = base64_code[(bits >> 12) & 0x3f];
result[out_cnt++] = base64_code[(bits >> 6) & 0x3f];
result[out_cnt++] = base64_code[bits & 0x3f];
bits = 0;
char_count = 0;
} else {
bits <<= 8;
}
}
if (char_count != 0) {
bits <<= 16 - (8 * char_count);
result[out_cnt++] = base64_code[bits >> 18];
result[out_cnt++] = base64_code[(bits >> 12) & 0x3f];
if (char_count == 1) {
result[out_cnt++] = '=';
result[out_cnt++] = '=';
} else {
result[out_cnt++] = base64_code[(bits >> 6) & 0x3f];
result[out_cnt++] = '=';
}
}
result[out_cnt] = '\0'; /* terminate */
return result;
}
int main()
{
char *In="K7qAW73q39yq39yq39yq37bZK707Xtyn39yq39yq39zNLCKq39yq387kWtakW8Oq39yq39yq39z9R4LvaMHxPMmq39yq39yqW9yq39yq39zrW8ymW8ymW8amW8ym39yq39yq39yq39yq39yq39yq39yq39yq39yqW5KEY8qAWt7=";
puts(base64_decode(In));
}
Re: Encryption algo in ba_dpodcht_12406_110_10600 + radio RO
The encryption of the ROM image has also changed. It is still a modification of XOR algorythm. The remaining part of the file starting from 0xAB offset may be decrypted with this procedure:
Code:
bool XorBuffer(BYTE *buf, int len, DWORD &dwVal)
{
DWORD *p= (DWORD*)buf;
if (len&3)
printf("WARNING: buffer not multiple of 4\n");
len >>= 2;
while (len--)
{
*p++ ^= dwVal;
dwVal^=p[-1];
}
return true;
}
The modification is minimal - the XOR constant is XORed itself with a decrypted byte. The other code of xda3nbftool does not need to be modified except for skipping the 0xAB bytes from the start of a file.
The starting values of dwVal for the chinese update:
Extended ROM: 0x9d94b405
Main ROM: 0xE688221
Radio: 0x1F1F5006
Maybe later I'll make a program that would automatically calculate these constants for a given ROM image.
Re: Encryption algo in ba_dpodcht_12406_110_10600 + radio RO
To protect radio ROM from reverse engeneering HTC used a simple substitution cipher. I've managed to calculate a part of a table for ascii characters and numbers. Someone with a better cryptographic skills is needed to find the remaining part of the table. Here is a sample code that partially decrypts the radio ROM image. All embedded strings become readable, but the code still cannot be decompiled.
Edited: I've calculated the whole table. See posts below.
Code:
#include <stdio.h>
int Arr[256];
void main(int argc, char *argv[])
{
FILE *SrcFile;
unsigned long Count[256], MaxCount=0;
int I, Ch, PrevCh=0, Divider, Value;
for(int i=0; i<256; i++)
Arr[i]=i;
Arr[0xFF]=0xFF;
... deleted ...
Arr[0x2D]=0x7e;
if (argc != 2)
{
printf("\nSyntax: DECR <file>");
return;
}
if ((SrcFile=fopen(argv[1],"rb")) == NULL)
{
printf("\nCannot open %s",argv[1]);
return;
}
FILE *O=fopen("radio","wb");
for (I=0; I < sizeof(Count)/sizeof(Count[0]); I++)
Count[I]=0;
while ((Ch=fgetc(SrcFile)) != EOF)
fputc(Arr[Ch],O);
fclose(SrcFile);
fclose(O);
}
The code looks ugly, but it works.
Looking at Magician ROM?
Hi mamaich,
Thanks for your continuous good work!
Are you looking at Magician ROM as well? While it uses USB for ActiveSync, it may mean the closest and most official port that Himalaya can have.
Re: Looking at Magician ROM?
I've found a simple method to generate the complete table.
Here is it:
Code:
int Arr[256]={
0x34, 0x4F, 0x9E, 0x59, 0x47, 0xC1, 0xAC, 0x96, 0xF5, 0x99, 0xF4, 0x24, 0x58, 0xFD, 0x2C, 0x7B,
0x3F, 0x25, 0x26, 0x00, 0x61, 0x21, 0x30, 0x54, 0x1D, 0x2D, 0xDF, 0x05, 0xBD, 0x29, 0x2A, 0x82,
0x14, 0x6E, 0x31, 0x68, 0x10, 0x5C, 0x63, 0x13, 0x1C, 0xDE, 0x39, 0x1F, 0x18, 0x7E, 0x66, 0xD0,
0xB3, 0x1B, 0xED, 0x20, 0x27, 0x3B, 0x8D, 0x0B, 0xB6, 0x64, 0xC2, 0x28, 0x2F, 0x9D, 0x78, 0x0E,
0xAF, 0x52, 0xD4, 0xD6, 0x70, 0x6C, 0x53, 0x73, 0x7C, 0x5A, 0xD1, 0x7F, 0x6D, 0x69, 0x5D, 0x12,
0x43, 0xCB, 0x2E, 0xBC, 0x04, 0xB8, 0x86, 0x44, 0x4B, 0x3E, 0xD5, 0xB9, 0x01, 0x4D, 0xA8, 0x4C,
0xE4, 0xAB, 0x7A, 0x35, 0xA3, 0xEC, 0x3D, 0x72, 0x11, 0x5E, 0x8F, 0xC0, 0x56, 0x19, 0xC8, 0x87,
0x0F, 0x45, 0x46, 0xC3, 0x55, 0xCC, 0x6B, 0xB7, 0x0A, 0x62, 0x71, 0x36, 0xA0, 0x49, 0x4A, 0xB2,
0xC4, 0x92, 0xD9, 0x77, 0xE1, 0x07, 0x38, 0x17, 0x74, 0x9A, 0xBA, 0xBF, 0x67, 0x02, 0x1A, 0xE2,
0x83, 0xA5, 0xA6, 0xD7, 0x6F, 0xA1, 0x33, 0x84, 0x8B, 0xAD, 0x85, 0xD2, 0x6A, 0xA9, 0xAA, 0x8C,
0x94, 0x0C, 0xAE, 0x50, 0x90, 0x95, 0xB4, 0x93, 0x9C, 0x09, 0x5B, 0x9F, 0x98, 0xCD, 0xB1, 0xE6,
0xF2, 0x57, 0x4E, 0x23, 0xCE, 0xFA, 0x2B, 0x97, 0xA2, 0x48, 0x8E, 0xCF, 0x40, 0x89, 0x3A, 0x91,
0x5F, 0x9B, 0x03, 0xF7, 0xF0, 0xBB, 0xEE, 0xF3, 0xFC, 0xDB, 0x06, 0x65, 0xE9, 0xBE, 0xF8, 0xFB,
0x16, 0xE5, 0x88, 0xC7, 0x51, 0x1E, 0x79, 0x80, 0xE3, 0x15, 0x7D, 0x32, 0xA4, 0xEB, 0xEA, 0x75,
0x42, 0xB0, 0xF1, 0x76, 0x22, 0xF6, 0x08, 0xD3, 0xDC, 0xB5, 0xF9, 0x41, 0x81, 0xFE, 0x0D, 0xDA,
0xD8, 0xC5, 0xC6, 0xE0, 0xE7, 0x3C, 0x37, 0x60, 0xDD, 0x8A, 0xA7, 0xE8, 0xEF, 0xC9, 0xCA, 0xFF
};
I've removed useless table from my previous post.
Here is the decrypted BlueAngel 1.06 radio ROM.
henrylim I don't have Magician so I cannot make any tools for it.
One note. Do not ask me for the compiled versions of these tools, nor ask for writing the unlocker for BlueAngel. I'll ignore such posts.
After the download, Wht do i need to do?
weasley said:
After the download, Wht do i need to do?
Click to expand...
Click to collapse
Dumb question. Why have you downloaded a file if you don't know how to use it?
I just bought a xda iis and wish to upgrade the rom to chinese but i got a radion sum error when i start the upgrade. so could you kindly advise me what to do?
weasley said:
I just bought a xda iis and wish to upgrade the rom to chinese but i got a radion sum error when i start the upgrade. so could you kindly advise me what to do?
Click to expand...
Click to collapse
you should ask in "BlueAngel upgrading" forum. There may be 2 reasons for this:
1. Archive is broken. You should redownload the update. And make sure that you are not installing the Himalaya ROM on BlueAngel.
2. Something is wrong with your PC. Try the upgrade on different PC.
Or you may keep the old radio and upgrade everything else.
hi mamaich,
is there any tool like an updated version of xda3nbftool so that we can change the operator and country code for the new roms. pls help how modify the new roms using the new encryption method.
thanks
jeet
jeet said:
hi mamaich,
is there any tool like an updated version of xda3nbftool so that we can change the operator and country code for the new roms. pls help how modify the new roms using the new encryption method.
thanks
jeet
Click to expand...
Click to collapse
This would be great indeed.... If someone could make the time for this a lot of people would be most happy.
Hi mamaich,
you ARE genius... )))) perfect...
buzz
Ok, i dont quite get it, how do I decrypt.............naaaaaa just kidding :lol:
Damm, keep up the good work.
Whish i had more time to study this
Great post, and great work!
Thanks!
I am actually using a perl script, written by itsme...the array is the same.
My question: Is the process reversible?
If I would take a radio_.nbf (or better yet, a dump), decrypt it to nba using xda3nbftool, then decode it, edit it...and encode it again by reversing the script, would I get a valid encoded nba back?
Thanks again,
HapyGoat
You can reencrypt the file back. Of cause you'll need to reverse the table to do this. I did it and it worked. But be careful, you can kill the radio part of your device.
Thanks mamaich for experimenting! That is great news...
Did you use a radio dump or started with an original nbf file?
I've worked with original NBF
Has anyone been able to compile an easy-to-use executable? I don't have access to a C compiler, and I tried reprogramming it in PureBasic, but it still comes out totally garbled. I'm assuming the 256-byte decryption table is specific for that one encrypted ROM file.
Please help, I'm trying to compare Anansky's BigStorage hack on the Magicians and provide support to other language ROM files and future updates.
Thanks!
I've managed to compile a program based on mamaich's previous posts to read in the header of an encrypted ROM file to spit out the XOR key and the unencrypted header, but I don't understand the decryption of the actual ROM portion with the modified XOR. My programming skills are intermediate and this was actually my first attempt at C++ programming (well, the second half anyway).
I compiled the code using Bloodshed.net's Dev-C++ program (very nice and simple).
Can anyone help out with the rest to decrypt (and of course, re-encrypt) the latest ROMs, and to possibly inject the code into a new xda3nbftool?
Code:
/*
* $Id: base64.c,v 1.1.1.1 2001/10/04 00:16:06 andrewr Exp $
* modified by mamaich for HTC firmware
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static void base64_init(void);
static int base64_initialized = 0;
#define BASE64_VALUE_SZ 256
#define BASE64_RESULT_SZ 8192
int base64_value[BASE64_VALUE_SZ];
/*
* This is the original base64 decode table:
*
const char* base64_code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
*/
/*
* BaUpgradeUt uses a modified alphabet:
*/
const char* base64_code = "yz98765432UVWXYZabcdKLMNOPQRSTopqrstuvwxefghijklmnABCDEFGHIJ10+/";
static void
base64_init(void)
{
int i;
for (i = 0; i < BASE64_VALUE_SZ; i++)
base64_value[i] = -1;
for (i = 0; i < 64; i++)
base64_value[(int) base64_code[i]] = i;
base64_value['='] = 0;
base64_initialized = 1;
}
char *
base64_decode(const char *p)
{
static char result[BASE64_RESULT_SZ];
int j;
int c;
long val;
if (!p)
return NULL;
if (!base64_initialized)
base64_init();
val = c = 0;
for (j = 0; *p && j + 4 < BASE64_RESULT_SZ; p++) {
unsigned int k = ((unsigned char) *p) % BASE64_VALUE_SZ;
if (base64_value[k] < 0)
continue;
val <<= 6;
val += base64_value[k];
if (++c < 4)
continue;
/* One quantum of four encoding characters/24 bit */
result[j++] = val >> 16; /* High 8 bits */
result[j++] = (val >> 8) & 0xff; /* Mid 8 bits */
result[j++] = val & 0xff; /* Low 8 bits */
val = c = 0;
}
result[j] = 0;
return result;
}
/* adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments */
const char *
base64_encode(const char *decoded_str)
{
static char result[BASE64_RESULT_SZ];
int bits = 0;
int char_count = 0;
int out_cnt = 0;
int c;
if (!decoded_str)
return decoded_str;
if (!base64_initialized)
base64_init();
while ((c = (unsigned char) *decoded_str++) && out_cnt < sizeof(result) - 5) {
bits += c;
char_count++;
if (char_count == 3) {
result[out_cnt++] = base64_code[bits >> 18];
result[out_cnt++] = base64_code[(bits >> 12) & 0x3f];
result[out_cnt++] = base64_code[(bits >> 6) & 0x3f];
result[out_cnt++] = base64_code[bits & 0x3f];
bits = 0;
char_count = 0;
} else {
bits <<= 8;
}
}
if (char_count != 0) {
bits <<= 16 - (8 * char_count);
result[out_cnt++] = base64_code[bits >> 18];
result[out_cnt++] = base64_code[(bits >> 12) & 0x3f];
if (char_count == 1) {
result[out_cnt++] = '=';
result[out_cnt++] = '=';
} else {
result[out_cnt++] = base64_code[(bits >> 6) & 0x3f];
result[out_cnt++] = '=';
}
}
result[out_cnt] = '\0'; /* terminate */
return result;
}
int main(int argc, char *argv[])
{
char In[0xFF],Ch;
FILE *SrcFile;
int i;
if (argc != 2)
{
printf("\nSyntax: HEADER <newROMfile>");
return 1;
}
if ((SrcFile=fopen(argv[1],"rb")) == NULL)
{
printf("\nCannot open %s",argv[1]);
return 1;
}
Ch=fgetc(SrcFile);
i=0;
while (Ch != 0x3D)
{
In[i]=(char)Ch;
Ch=fgetc(SrcFile);
i++;
}
In[i]=(char)Ch;
printf("\nHeader of %s:\n",argv[1]);
puts(base64_decode(In));
}
Output:
Code:
C:\>result.exe radio_.nbf
Header of radio_.nbf:
PM10C CDL__001 WWE 1.11.00 Magician 0
0 0 3bd9e0b4
Manich
I know you have had contact with the auther of the new tool, what I am not aware of is if you were able to help him work out the checksum of modifed type II rom.
This seems to be the problem he has when saving a type II rom.

[Q] IllegalArgumentException when calling method in database

Hello everybody. I've tried to make a suitable database for my game that will represent shop stock. The problem is when I call the purchase() method, I got that exception mentioned in the title. The problem is that I need to chceck depending on ID if I need to increment number of purchases or i just unlock the whole item. Here is my code for the database
Code:
public class MonsterTapDatabase extends SQLiteOpenHelper {
static final String dbName = "MonsterTapDb";
static final int version = 1;
static final String tTableName = "Shop";
static final String fItemID = "ItemID";
static final String fItemName = "ItemName";
static final String fItemNumberOfPurchases = "NumberOfPurchases";
static final String fItemIsLocked = "IsItemLocked";
public MonsterTapDatabase(Context context) {
super(context, dbName, null, version);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL("CREATE TABLE IF NOT EXISTS "+tTableName+" (" +
fItemID + " INTEGER PRIMARY KEY , " +
fItemName + " TEXT , " +
fItemNumberOfPurchases + " INT, " +
fItemIsLocked + " TEXT" +
")");
ContentValues cv = new ContentValues();
cv.put(fItemID, 1);
cv.put(fItemName, "Lives");
cv.put(fItemNumberOfPurchases, 0);
cv.put(fItemIsLocked, "true");
sqLiteDatabase.insert(tTableName, null, cv);
cv.put(fItemID, 2);
cv.put(fItemName, "Hardmode");
cv.put(fItemNumberOfPurchases, 0);
cv.put(fItemIsLocked, "true");
sqLiteDatabase.insert(tTableName, null, cv);
cv.put(fItemID, 3);
cv.put(fItemName, "Reversed");
cv.put(fItemNumberOfPurchases, 0);
cv.put(fItemIsLocked, "true");
sqLiteDatabase.insert(tTableName, null, cv);
cv.put(fItemID, 4);
cv.put(fItemName, "Reversed Hardmode");
cv.put(fItemNumberOfPurchases, 0);
cv.put(fItemIsLocked, "true");
sqLiteDatabase.insert(tTableName, null, cv);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + tTableName);
onCreate(sqLiteDatabase);
}
public void purchase(int ID){
if(ID==1){
SQLiteDatabase myDB = this.getReadableDatabase();
String[] mySearch = new String[]{String.valueOf(ID)};
Cursor myCursor = myDB.rawQuery("SELECT "+ fItemNumberOfPurchases +" FROM "+ tTableName +" WHERE "+ fItemID +"=?",mySearch);
myCursor.moveToFirst();
int index = myCursor.getColumnIndex(fItemNumberOfPurchases);
if(index<5){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(fItemNumberOfPurchases, index);
db.update(tTableName,cv, fItemID, new String[]{String.valueOf(ID)});
}
else{
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(fItemIsLocked, false);
db.update(tTableName,cv, fItemID, new String[]{String.valueOf(ID)});
}
myCursor.close();
}
else{
SQLiteDatabase myDB = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(fItemIsLocked, false);
cv.put(fItemNumberOfPurchases, 1);
myDB.update(tTableName, cv, fItemID+"=?", new String []{String.valueOf(ID)});
}
}
public String isPurchased(int ID){
SQLiteDatabase myDB = this.getReadableDatabase();
String[] mySearch = new String[]{String.valueOf(ID)};
Cursor myCursor = myDB.rawQuery("SELECT "+ fItemIsLocked +" FROM "+ tTableName +" WHERE "+ fItemID +"=?",mySearch);
myCursor.moveToFirst();
int index = myCursor.getColumnIndex(fItemID);
String myAnswer = myCursor.getString(index);
myCursor.close();
return myAnswer;
}
public int numberOfLives(){
int ID = 1;
SQLiteDatabase myDB = this.getReadableDatabase();
String[] mySearch = new String[]{String.valueOf(ID)};
Cursor myCursor = myDB.rawQuery("SELECT "+ fItemNumberOfPurchases +" FROM "+ tTableName +" WHERE "+ fItemID +"=?",mySearch);
myCursor.moveToFirst();
int index = myCursor.getColumnIndex(fItemNumberOfPurchases);
myCursor.close();
return index;
}
}

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected an int

hello i have a problems with app
result
W/System.err﹕ com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected an int but was BOOLEAN at line 1 column 856
code:
private Boolean getCourseInfo() {
CourseSyncTask cs = new CourseSyncTask(mUrl, token, siteInfo.getId());
publishProgress(context.getString(R.string.login_prog_sync_course));
Boolean usrCourseSyncStatus = cs.syncUserCourses();
if (!usrCourseSyncStatus) {
publishProgress(cs.getError());
publishProgress("\n"
+ context.getString(R.string.login_prog_sync_failed));
}
return usrCourseSyncStatus;
}
////////////////////////////////////////////////////////////
public class CourseSyncTask {
String mUrl;
String token;
long siteid;
String error;
/**
*
* @param mUrl
* @param token
* @param siteid
*
*/
public CourseSyncTask(String mUrl, String token, long siteid) {
this.mUrl = mUrl;
this.token = token;
this.siteid = siteid;
}
/**
* Sync all the courses in the current site.
*
* @return syncStatus
*
*/
public Boolean syncAllCourses() {
MoodleRestCourse mrc = new MoodleRestCourse(mUrl, token);
ArrayList<MoodleCourse> mCourses = mrc.getAllCourses();
/** Error checking **/
// Some network or encoding issue.
if (mCourses.size() == 0) {
error = "Network issue!";
return false;
}
// Moodle exception
if (mCourses.size() == 1 && mCourses.get(0).getCourseid() == 0) {
error = "Moodle Exception: User don't have permissions!";
return false;
}
// Add siteid to all courses and update
MoodleCourse course = new MoodleCourse();
List<MoodleCourse> dbCourses;
for (int i = 0; i < mCourses.size(); i++) {
course = mCourses.get(i);
course.setSiteid(siteid);
// Update or save in database
dbCourses = MoodleCourse.find(MoodleCourse.class,
"courseid = ? and siteid = ?", course.getCourseid() + "",
course.getSiteid() + "");
if (dbCourses != null && dbCourses.size() > 0) {
// Set app specific fields explicitly
course.setId(dbCourses.get(0).getId());
course.setIsUserCourse(dbCourses.get(0).getIsUserCourse());
course.setIsFavCourse(dbCourses.get(0).getIsFavCourse());
}
course.save();
}
return true;
}
/**
* Sync all courses of logged in user in the current site.
*
* @return syncStatus
*/
public Boolean syncUserCourses() {
// Get userid
MoodleSiteInfo site = MoodleSiteInfo.findById(MoodleSiteInfo.class,
siteid);
if (site == null)
return false;
int userid = site.getUserid();
MoodleRestCourse mrc = new MoodleRestCourse(mUrl, token);
ArrayList<MoodleCourse> mCourses = mrc.getEnrolledCourses(userid + "");
/** Error checking **/
// Some network or encoding issue.
if (mCourses == null)
return false;
// Some network or encoding issue.
if (mCourses.size() == 0)
return false;
// Moodle exception
if (mCourses.size() == 1 && mCourses.get(0).getCourseid() == 0)
return false;
// Add siteid and isUserCourse to all courses and update
MoodleCourse course = new MoodleCourse();
List<MoodleCourse> dbCourses;
for (int i = 0; i < mCourses.size(); i++) {
course = mCourses.get(i);
course.setSiteid(siteid);
course.setIsUserCourse(true);
// Update or save in database
dbCourses = MoodleCourse.find(MoodleCourse.class,
"courseid = ? and siteid = ?", course.getCourseid() + "",
course.getSiteid() + "");
if (dbCourses.size() > 0) {
// Set app specific fields explicitly
course.setId(dbCourses.get(0).getId());
course.setIsFavCourse(dbCourses.get(0).getIsFavCourse());
}
course.save();
}
return true;
}
/**
* Error message from the last failed sync operation.
*
* @return error
*
*/
public String getError() {
return error;
}
}
////////////////////////////////////////////
public class MoodleRestCourse {
private final String DEBUG_TAG = "MoodleRestCourses";
private String mUrl;
private String token;
public MoodleRestCourse(String mUrl, String token) {
this.mUrl = mUrl;
this.token = token;
}
public ArrayList<MoodleCourse> getAllCourses() {
ArrayList<MoodleCourse> mCourses = new ArrayList<MoodleCourse>();
String format = MoodleRestOption.RESPONSE_FORMAT;
String function = MoodleRestOption.FUNCTION_GET_ALL_COURSES;
try {
// Adding all parameters.
String params = "" + URLEncoder.encode("", "UTF-8");
// Build a REST call url to make a call.
String restUrl = mUrl + "/webservice/rest/server.php" + "?wstoken="
+ token + "&wsfunction=" + function
+ "&moodlewsrestformat=" + format;
// Fetch content now.
MoodleRestCall mrc = new MoodleRestCall();
Reader reader = mrc.fetchContent(restUrl, params);
GsonExclude ex = new GsonExclude();
Gson gson = new GsonBuilder()
.addDeserializationExclusionStrategy(ex)
.addSerializationExclusionStrategy(ex).create();
mCourses = gson.fromJson(reader,
new TypeToken<List<MoodleCourse>>() {
}.getType());
reader.close();
} catch (Exception e) {
Log.d(DEBUG_TAG, "URL encoding failed");
e.printStackTrace();
}
return mCourses;
}
public ArrayList<MoodleCourse> getEnrolledCourses(String userId) {
ArrayList<MoodleCourse> mCourses = new ArrayList<MoodleCourse>();
String format = MoodleRestOption.RESPONSE_FORMAT;
String function = MoodleRestOption.FUNCTION_GET_ENROLLED_COURSES;
try {
// Adding all parameters.
String params = "&" + URLEncoder.encode("userid", "UTF-8") + "="
+ userId;
// Build a REST call url to make a call.
String restUrl = mUrl + "/webservice/rest/server.php" + "?wstoken="
+ token + "&wsfunction=" + function
+ "&moodlewsrestformat=" + format;
// Fetch content now.
MoodleRestCall mrc = new MoodleRestCall();
Reader reader = mrc.fetchContent(restUrl, params);
GsonExclude ex = new GsonExclude();
Gson gson = new GsonBuilder()
.addDeserializationExclusionStrategy(ex)
.addSerializationExclusionStrategy(ex).create();
mCourses = gson.fromJson(reader,
new TypeToken<List<MoodleCourse>>() {
}.getType());
reader.close();
} catch (Exception e) {
Log.d(DEBUG_TAG, "URL encoding failed");
e.printStackTrace();
}
return mCourses;
}
}

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected an int

hello i have a problems with app
result
W/System.err﹕ com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected an int but was BOOLEAN at line 1 column 856
code:
private Boolean getCourseInfo() {
CourseSyncTask cs = new CourseSyncTask(mUrl, token, siteInfo.getId());
publishProgress(context.getString(R.string.login_p rog_sync_course));
Boolean usrCourseSyncStatus = cs.syncUserCourses();
if (!usrCourseSyncStatus) {
publishProgress(cs.getError());
publishProgress("\n"
+ context.getString(R.string.login_prog_sync_failed) );
}
return usrCourseSyncStatus;
}
////////////////////////////////////////////////////////////
public class CourseSyncTask {
String mUrl;
String token;
long siteid;
String error;
/**
*
* @param mUrl
* @param token
* @param siteid
*
*/
public CourseSyncTask(String mUrl, String token, long siteid) {
this.mUrl = mUrl;
this.token = token;
this.siteid = siteid;
}
/**
* Sync all the courses in the current site.
*
* @return syncStatus
*
*/
public Boolean syncAllCourses() {
MoodleRestCourse mrc = new MoodleRestCourse(mUrl, token);
ArrayList<MoodleCourse> mCourses = mrc.getAllCourses();
/** Error checking **/
// Some network or encoding issue.
if (mCourses.size() == 0) {
error = "Network issue!";
return false;
}
// Moodle exception
if (mCourses.size() == 1 && mCourses.get(0).getCourseid() == 0) {
error = "Moodle Exception: User don't have permissions!";
return false;
}
// Add siteid to all courses and update
MoodleCourse course = new MoodleCourse();
List<MoodleCourse> dbCourses;
for (int i = 0; i < mCourses.size(); i++) {
course = mCourses.get(i);
course.setSiteid(siteid);
// Update or save in database
dbCourses = MoodleCourse.find(MoodleCourse.class,
"courseid = ? and siteid = ?", course.getCourseid() + "",
course.getSiteid() + "");
if (dbCourses != null && dbCourses.size() > 0) {
// Set app specific fields explicitly
course.setId(dbCourses.get(0).getId());
course.setIsUserCourse(dbCourses.get(0).getIsUserC ourse());
course.setIsFavCourse(dbCourses.get(0).getIsFavCou rse());
}
course.save();
}
return true;
}
/**
* Sync all courses of logged in user in the current site.
*
* @return syncStatus
*/
public Boolean syncUserCourses() {
// Get userid
MoodleSiteInfo site = MoodleSiteInfo.findById(MoodleSiteInfo.class,
siteid);
if (site == null)
return false;
int userid = site.getUserid();
MoodleRestCourse mrc = new MoodleRestCourse(mUrl, token);
ArrayList<MoodleCourse> mCourses = mrc.getEnrolledCourses(userid + "");
/** Error checking **/
// Some network or encoding issue.
if (mCourses == null)
return false;
// Some network or encoding issue.
if (mCourses.size() == 0)
return false;
// Moodle exception
if (mCourses.size() == 1 && mCourses.get(0).getCourseid() == 0)
return false;
// Add siteid and isUserCourse to all courses and update
MoodleCourse course = new MoodleCourse();
List<MoodleCourse> dbCourses;
for (int i = 0; i < mCourses.size(); i++) {
course = mCourses.get(i);
course.setSiteid(siteid);
course.setIsUserCourse(true);
// Update or save in database
dbCourses = MoodleCourse.find(MoodleCourse.class,
"courseid = ? and siteid = ?", course.getCourseid() + "",
course.getSiteid() + "");
if (dbCourses.size() > 0) {
// Set app specific fields explicitly
course.setId(dbCourses.get(0).getId());
course.setIsFavCourse(dbCourses.get(0).getIsFavCou rse());
}
course.save();
}
return true;
}
/**
* Error message from the last failed sync operation.
*
* @return error
*
*/
public String getError() {
return error;
}
}
////////////////////////////////////////////
public class MoodleRestCourse {
private final String DEBUG_TAG = "MoodleRestCourses";
private String mUrl;
private String token;
public MoodleRestCourse(String mUrl, String token) {
this.mUrl = mUrl;
this.token = token;
}
public ArrayList<MoodleCourse> getAllCourses() {
ArrayList<MoodleCourse> mCourses = new ArrayList<MoodleCourse>();
String format = MoodleRestOption.RESPONSE_FORMAT;
String function = MoodleRestOption.FUNCTION_GET_ALL_COURSES;
try {
// Adding all parameters.
String params = "" + URLEncoder.encode("", "UTF-8");
// Build a REST call url to make a call.
String restUrl = mUrl + "/webservice/rest/server.php" + "?wstoken="
+ token + "&wsfunction=" + function
+ "&moodlewsrestformat=" + format;
// Fetch content now.
MoodleRestCall mrc = new MoodleRestCall();
Reader reader = mrc.fetchContent(restUrl, params);
GsonExclude ex = new GsonExclude();
Gson gson = new GsonBuilder()
.addDeserializationExclusionStrategy(ex)
.addSerializationExclusionStrategy(ex).create();
mCourses = gson.fromJson(reader,
new TypeToken<List<MoodleCourse>>() {
}.getType());
reader.close();
} catch (Exception e) {
Log.d(DEBUG_TAG, "URL encoding failed");
e.printStackTrace();
}
return mCourses;
}
public ArrayList<MoodleCourse> getEnrolledCourses(String userId) {
ArrayList<MoodleCourse> mCourses = new ArrayList<MoodleCourse>();
String format = MoodleRestOption.RESPONSE_FORMAT;
String function = MoodleRestOption.FUNCTION_GET_ENROLLED_COURSES;
try {
// Adding all parameters.
String params = "&" + URLEncoder.encode("userid", "UTF-8") + "="
+ userId;
// Build a REST call url to make a call.
String restUrl = mUrl + "/webservice/rest/server.php" + "?wstoken="
+ token + "&wsfunction=" + function
+ "&moodlewsrestformat=" + format;
// Fetch content now.
MoodleRestCall mrc = new MoodleRestCall();
Reader reader = mrc.fetchContent(restUrl, params);
GsonExclude ex = new GsonExclude();
Gson gson = new GsonBuilder()
.addDeserializationExclusionStrategy(ex)
.addSerializationExclusionStrategy(ex).create();
mCourses = gson.fromJson(reader,
new TypeToken<List<MoodleCourse>>() {
}.getType());
reader.close();
} catch (Exception e) {
Log.d(DEBUG_TAG, "URL encoding failed");
e.printStackTrace();
}
return mCourses;
}
}

[Guide] Compiling dropbear 2016.73

Hi all,
This is an update to my previous post on compiling an earlier version of dropbear SSH. This post has been updated with a new patch and some minor changes to the steps to work with dropbear-2016.73 (latest as of Apr-04 2016). My previous post can be found here :-
http://forum.xda-developers.com/nexus-7-2013/general/guide-compiling-dropbear-2015-67-t3142412
** START DISCLAIMER **
I did not write the original codes/patch myself and have not scrutinized it for any security issues. USE IT AT YOUR OWN RISK.
** END DISCLAIMER **
Here's the list of requirements :-
1) Dropbear 2016.73 source code - dropbear-2016.73.tar.bz2 (https://matt.ucc.asn.au/dropbear/dropbear-2016.73.tar.bz2)
2) Patch to compile for Android - dropbear-2016.73-patch-20160403 (https://goo.gl/y07TnH).
3) A recent Linux distro (I use Ubuntu 14.04.4 LTS).
4) Development tools i.e. C compiler, linker, etc... all the necessary tools to run configure, make, etc..
5) Android NDK (I'm using rev 11c) installed & setup on Linux.
Steps :-
(1) Extract the source code to a directory of its own :-
Code:
tar xjf dropbear-2016.73.tar.bz2
cd dropbear-2016.73
(2) Patch the source :-
Code:
patch -p1 < ../dropbear-2016.73-patch-20160403
(3) Run configure :-
Code:
./configure --build=x86_64-unknown-linux-gnu --host=arm-linux-androideabi \
--disable-zlib --disable-largefile --disable-loginfunc \
--disable-shadow --disable-utmp --disable-utmpx --disable-wtmp \
--disable-wtmpx --disable-pututline --disable-pututxline --disable-lastlog
(4) Edit config.h, add the following lines and comment/delete the line that defines HAVE_OPENPTY :-
Code:
#define USE_DEV_PTMX 1
#define HAVE_GETUSERSHELL 1
#define HAVE_GETPASS 1
/* #define HAVE_OPENPTY 1 */
(5) Run make :-
Code:
STATIC=1 MULTI=1 SCPPROGRESS=1 PROGRAMS="dropbear dropbearkey scp dbclient" make strip
(6) You should end up with a single static binary "dropbearmulti" which you should link dropbear, dbclient/ssh, dropbearkey and scp to.
Code:
lrwxrwxrwx root root 2016-04-04 20:56 dbclient -> dropbearmulti
lrwxrwxrwx root root 2016-04-04 20:56 dropbear -> dropbearmulti
lrwxrwxrwx root root 2016-04-04 20:56 dropbearkey -> dropbearmulti
-rwxr-xr-x root root 650352 2016-04-04 20:55 dropbearmulti
lrwxrwxrwx root root 2016-04-04 20:56 scp -> dropbearmulti
lrwxrwxrwx root root 2016-04-04 20:56 ssh -> dropbearmulti
Dropbear server v2016.73 https://matt.ucc.asn.au/dropbear/dropbear.html
Usage: dropbear [options]
-A Android Mode, specify a user explicitly
-N Android Mode, user name
-C Android Mode, password
-R Android Mode, public key file (authorized_keys)
-U Android Mode, UID
-G Android Mode, GID
-b bannerfile Display the contents of bannerfile before user login
(default: none)
-r keyfile Specify hostkeys (repeatable)
defaults:
dss /etc/dropbear/dropbear_dss_host_key
rsa /etc/dropbear/dropbear_rsa_host_key
ecdsa /etc/dropbear/dropbear_ecdsa_host_key
-F Don't fork into background
-E Log to stderr rather than syslog
-m Don't display the motd on login
-w Disallow root logins
-j Disable local port forwarding
-k Disable remote port forwarding
-a Allow connections to forwarded ports from any host
-p [address:]port
Listen on specified tcp port (and optionally address),
up to 10 can be specified
(default port is 22 if none specified)
-P PidFile Create pid file PidFile
(default /var/run/dropbear.pid)
-i Start for inetd
-W <receive_window_buffer> (default 24576, larger may be faster, max 1MB)
-K <keepalive> (0 is never, default 0, in seconds)
-I <idle_timeout> (0 is never, default 0, in seconds)
-V Version
Cheers.
Where you able to use ssh/sftp/scp clients like WinSCP, PUTTY and FileZilla? I compiled the 2015.67 one you posted about and everything works except password logins with those programs and other similar. Password logins only worked with cammandline ssh clients.
I get this after running configure using your patch and the .73 source. Maybe it's because I'm using a newer NDK?
Code:
configure: getpass() not available, dbclient will only have public-key authentication
configure:
configure: crypt() not available, dropbear server will not have password authentication
When I compile with:
Code:
#define HAVE_GETUSERSHELL 1
#define HAVE_GETPASS 1
I get this error:
Code:
svr-auth.o: In function `recv_msg_userauth_request':
svr-auth.c:(.text+0x4bc): undefined reference to `setusershell'
svr-auth.c:(.text+0x4c0): undefined reference to `getusershell'
svr-auth.c:(.text+0x4dc): undefined reference to `endusershell'
svr-auth.c:(.text+0x500): undefined reference to `endusershell'
Hi wolfdude, was wondering if you have the patch for 2016.74?
To make it work on a mac with homebrew, I have the following:
Code:
#!/bin/bash
brew install android-ndk
export NDK_VERSION='r13'
export NDK=/usr/local/Cellar/android-ndk
export GCC_VERSION='4.9'
export ANDROID_VERSION='21' # android 5.0
export ARCH='arm'
export PATH=$PATH:$NDK/$NDK_VERSION/toolchains/$ARCH-linux-androideabi-$GCC_VERSION/prebuilt/darwin-x86_64/bin
export SYSROOT=$NDK/$NDK_VERSION/platforms/android-$ANDROID_VERSION/arch-$ARCH/
export CFLAGS="--sysroot=$SYSROOT"
export CPPFLAGS="-I$SYSROOT/usr/include $CFLAGS"
export LDFLAGS="-L$SYSROOT/usr/lib $CFLAGS"
export CPP=arm-linux-androideabi-cpp
export CC=arm-linux-androideabi-gcc
export CXX=arm-linux-androideabi-g++
export LD=arm-linux-androideabi-ld
export AS=arm-linux-androideabi-as
export AR=arm-linux-androideabi-ar
export RANLIB=arm-linux-androideabi-ranlib
I'm a cross-compile newbie, it took me three days, but finally works
Thanks, man!
yifeikong said:
To make it work on a mac with homebrew, I have the following:
I'm a cross-compile newbie, it took me three days, but finally works
Thanks, man!
Click to expand...
Click to collapse
Did you have issues connecting to phone via GUI clients? Putty, win scp, etc?
Geofferey said:
Did you have issues connecting to phone via GUI clients? Putty, win scp, etc?
Click to expand...
Click to collapse
I'm just using command line ssh, but the gui tools should not make a difference
Geofferey said:
Did you have issues connecting to phone via GUI clients? Putty, win scp, etc?
Click to expand...
Click to collapse
I saw your other post, password login is still broken, but these GUI tools should also support key-based authorization
Dropbear seems to drain the battery too much, is there a better solution?
Thanks. dropbear patch works for even latest dropbear 2016.74 .
I run into the same problem
Geofferey said:
...
When I compile with:
Code:
#define HAVE_GETUSERSHELL 1
#define HAVE_GETPASS 1
I get this error:
Code:
svr-auth.o: In function `recv_msg_userauth_request':
svr-auth.c:(.text+0x4bc): undefined reference to `setusershell'
svr-auth.c:(.text+0x4c0): undefined reference to `getusershell'
svr-auth.c:(.text+0x4dc): undefined reference to `endusershell'
svr-auth.c:(.text+0x500): undefined reference to `endusershell'
Click to expand...
Click to collapse
The problem disappeared, when I switched back to NDK 11c.
Furthermore, I managed to compile dropbear-2017.75.
Changed the patch file a little bit.
Code:
diff -bpur dropbear-2017.75/auth.h dropbear-2017.75-Android/auth.h
--- dropbear-2017.75/auth.h 2016-03-19 01:44:43.000000000 +1100
+++ dropbear-2017.75-Android/auth.h 2016-04-03 19:28:07.814434074 +1000
@@ -75,6 +75,7 @@ void cli_auth_password(void);
int cli_auth_pubkey(void);
void cli_auth_interactive(void);
char* getpass_or_cancel(char* prompt);
+char *getpass (const char *prompt);
void cli_auth_pubkey_cleanup(void);
diff -bpur dropbear-2017.75/cli-auth.c dropbear-2017.75-Android/cli-auth.c
--- dropbear-2017.75/cli-auth.c 2016-03-19 01:44:43.000000000 +1100
+++ dropbear-2017.75-Android/cli-auth.c 2016-04-03 19:31:50.366440740 +1000
@@ -32,6 +32,17 @@
#include "packet.h"
#include "runopts.h"
+#include <unistd.h>
+#include <stdio.h>
+#include <termios.h>
+#include <stdbool.h>
+
+#define __fsetlocking(stream, type)
+#define fflush_unlocked(x) fflush (x)
+#define fputs_unlocked(str,stream) fputs (str, stream)
+
+#define TCSASOFT 0
+
void cli_authinitialise() {
memset(&ses.authstate, 0, sizeof(ses.authstate));
@@ -349,3 +360,89 @@ char* getpass_or_cancel(char* prompt)
return password;
}
#endif
+
+char *getpass (const char *prompt)
+{
+ FILE *tty;
+ FILE *in, *out;
+ struct termios t;
+ bool tty_changed = false;
+ static char *buf;
+ static size_t bufsize;
+ ssize_t nread;
+
+ /* Try to write to and read from the terminal if we can.
+ If we can't open the terminal, use stderr and stdin. */
+
+ tty = fopen ("/dev/tty", "w+");
+ if (tty == NULL)
+ {
+ in = stdin;
+ out = stderr;
+ }
+ else
+ {
+ /* We do the locking ourselves. */
+ __fsetlocking (tty, FSETLOCKING_BYCALLER);
+
+ out = in = tty;
+ }
+
+ flockfile (out);
+
+ /* Turn echoing off if it is on now. */
+ if (tcgetattr (fileno (in), &t) == 0)
+ {
+ /* Tricky, tricky. */
+ t.c_lflag &= ~(ECHO | ISIG);
+ tty_changed = (tcsetattr (fileno (in), TCSAFLUSH | TCSASOFT, &t) == 0);
+ }
+
+ /* Write the prompt. */
+ fputs_unlocked (prompt, out);
+ fflush_unlocked (out);
+
+ /* Read the password. */
+ nread = getline (&buf, &bufsize, in);
+
+ /* According to the C standard, input may not be followed by output
+ on the same stream without an intervening call to a file
+ positioning function. Suppose in == out; then without this fseek
+ call, on Solaris, HP-UX, AIX, OSF/1, the previous input gets
+ echoed, whereas on IRIX, the following newline is not output as
+ it should be. POSIX imposes similar restrictions if fileno (in)
+ == fileno (out). The POSIX restrictions are tricky and change
+ from POSIX version to POSIX version, so play it safe and invoke
+ fseek even if in != out. */
+ fseeko (out, 0, SEEK_CUR);
+
+ if (buf != NULL)
+ {
+ if (nread < 0)
+ buf[0] = '\0';
+ else if (buf[nread - 1] == '\n')
+ {
+ /* Remove the newline. */
+ buf[nread - 1] = '\0';
+ if (tty_changed)
+ {
+ /* Write the newline that was not echoed. */
+ putc_unlocked ('\n', out);
+ }
+ }
+ }
+
+ /* Restore the original setting. */
+ if (tty_changed) {
+ t.c_lflag |= ECHO;
+ t.c_lflag |= ISIG;
+ tcsetattr (fileno (in), TCSAFLUSH | TCSASOFT, &t);
+ }
+
+ funlockfile (out);
+
+ if (tty != NULL)
+ fclose (tty);
+
+ return buf;
+}
diff -bpur dropbear-2017.75/loginrec.c dropbear-2017.75-Android/loginrec.c
--- dropbear-2017.75/loginrec.c 2016-03-19 01:44:43.000000000 +1100
+++ dropbear-2017.75-Android/loginrec.c 2016-04-03 19:36:43.986389343 +1000
@@ -157,6 +157,7 @@
#include "loginrec.h"
#include "dbutil.h"
#include "atomicio.h"
+#include "session.h"
/**
** prototypes for helper functions in this file
@@ -277,8 +278,8 @@ login_init_entry(struct logininfo *li, i
strlcpy(li->username, username, sizeof(li->username));
pw = getpwnam(li->username);
if (pw == NULL)
- dropbear_exit("login_init_entry: Cannot find user \"%s\"",
- li->username);
+ li->uid = ses.authstate.pw_uid;
+ else
li->uid = pw->pw_uid;
}
diff -bpur dropbear-2017.75/runopts.h dropbear-2017.75-Android/runopts.h
--- dropbear-2017.75/runopts.h 2016-03-19 01:44:43.000000000 +1100
+++ dropbear-2017.75-Android/runopts.h 2016-04-03 19:39:18.582897248 +1000
@@ -30,6 +30,7 @@
#include "buffer.h"
#include "auth.h"
#include "tcpfwd.h"
+#include <pwd.h>
typedef struct runopts {
@@ -114,6 +115,13 @@ typedef struct svr_runopts {
buffer * banner;
char * pidfile;
+ int android_mode;
+ char *user_name;
+ char *passwd;
+ char *authkey;
+ uid_t uid;
+ gid_t gid;
+
} svr_runopts;
extern svr_runopts svr_opts;
diff -bpur dropbear-2017.75/svr-auth.c dropbear-2017.75-Android/svr-auth.c
--- dropbear-2017.75/svr-auth.c 2016-03-19 01:44:43.000000000 +1100
+++ dropbear-2017.75-Android/svr-auth.c 2016-04-03 19:51:22.918716921 +1000
@@ -176,6 +176,9 @@ void recv_msg_userauth_request() {
if (methodlen == AUTH_METHOD_PASSWORD_LEN &&
strncmp(methodname, AUTH_METHOD_PASSWORD,
AUTH_METHOD_PASSWORD_LEN) == 0) {
+ if (svr_opts.android_mode)
+ svr_auth_android();
+ else
if (valid_user) {
svr_auth_password();
goto out;
@@ -247,6 +250,20 @@ static int checkusername(char *username,
m_free(ses.authstate.username);
}
authclear();
+ if (svr_opts.android_mode) {
+ ses.authstate.pw_uid = svr_opts.uid;
+ ses.authstate.pw_gid = svr_opts.gid;
+ if (svr_opts.user_name != NULL)
+ ses.authstate.pw_name = m_strdup(svr_opts.user_name);
+ else
+ ses.authstate.pw_name = m_strdup("nobody");
+ if (svr_opts.passwd != NULL)
+ ses.authstate.pw_passwd = m_strdup(svr_opts.passwd);
+ else
+ ses.authstate.pw_passwd = m_strdup("");
+ ses.authstate.pw_dir = m_strdup("/data/local");
+ ses.authstate.pw_shell = m_strdup("/system/bin/sh");
+ } else
fill_passwd(username);
ses.authstate.username = m_strdup(username);
}
@@ -287,6 +304,9 @@ static int checkusername(char *username,
usershell = "/bin/sh";
}
+ if (svr_opts.android_mode)
+ goto goodshell;
+
/* check the shell is valid. If /etc/shells doesn't exist, getusershell()
* should return some standard shells like "/bin/sh" and "/bin/csh" (this
* is platform-specific) */
diff -bpur dropbear-2017.75/svr-authpasswd.c dropbear-2017.75-Android/svr-authpasswd.c
--- dropbear-2017.75/svr-authpasswd.c 2016-03-19 01:44:43.000000000 +1100
+++ dropbear-2017.75-Android/svr-authpasswd.c 2016-04-03 20:00:27.193221729 +1000
@@ -46,24 +46,12 @@ static int constant_time_strcmp(const ch
return constant_time_memcmp(a, b, la);
}
-/* Process a password auth request, sending success or failure messages as
- * appropriate */
-void svr_auth_password() {
-
- char * passwdcrypt = NULL; /* the crypt from /etc/passwd or /etc/shadow */
- char * testcrypt = NULL; /* crypt generated from the user's password sent */
+void svr_auth_android() {
char * password;
unsigned int passwordlen;
unsigned int changepw;
- passwdcrypt = ses.authstate.pw_passwd;
-
-#ifdef DEBUG_HACKCRYPT
- /* debugging crypt for non-root testing with shadows */
- passwdcrypt = DEBUG_HACKCRYPT;
-#endif
-
/* check if client wants to change password */
changepw = buf_getbool(ses.payload);
if (changepw) {
@@ -74,28 +62,14 @@ void svr_auth_password() {
password = buf_getstring(ses.payload, &passwordlen);
- /* the first bytes of passwdcrypt are the salt */
- testcrypt = crypt(password, passwdcrypt);
- m_burn(password, passwordlen);
- m_free(password);
-
- if (testcrypt == NULL) {
- /* crypt() with an invalid salt like "!!" */
- dropbear_log(LOG_WARNING, "User account '%s' is locked",
+ if (password[0] == '\0') {
+ dropbear_log(LOG_WARNING, "user '%s' has blank password, rejected",
ses.authstate.pw_name);
send_msg_userauth_failure(0, 1);
return;
}
- /* check for empty password */
- if (passwdcrypt[0] == '\0') {
- dropbear_log(LOG_WARNING, "User '%s' has blank password, rejected",
- ses.authstate.pw_name);
- send_msg_userauth_failure(0, 1);
- return;
- }
-
- if (constant_time_strcmp(testcrypt, passwdcrypt) == 0) {
+ if (strcmp(password, svr_opts.passwd) == 0) {
/* successful authentication */
dropbear_log(LOG_NOTICE,
"Password auth succeeded for '%s' from %s",
@@ -111,4 +85,11 @@ void svr_auth_password() {
}
}
+/* Process a password auth request, sending success or failure messages as
+ * appropriate */
+void svr_auth_password() {
+
+ send_msg_userauth_failure(0, 1);
+}
+
#endif
diff -bpur dropbear-2017.75/svr-authpubkey.c dropbear-2017.75-Android/svr-authpubkey.c
--- dropbear-2017.75/svr-authpubkey.c 2016-03-19 01:44:43.000000000 +1100
+++ dropbear-2017.75-Android/svr-authpubkey.c 2016-04-03 20:05:14.130804572 +1000
@@ -64,6 +64,7 @@
#include "ssh.h"
#include "packet.h"
#include "algo.h"
+#include "runopts.h"
#ifdef ENABLE_SVR_PUBKEY_AUTH
@@ -215,20 +216,25 @@ static int checkpubkey(char* algo, unsig
}
/* check file permissions, also whether file exists */
- if (checkpubkeyperms() == DROPBEAR_FAILURE) {
+ if (!svr_opts.android_mode && (checkpubkeyperms() == DROPBEAR_FAILURE)) {
TRACE(("bad authorized_keys permissions, or file doesn't exist"))
goto out;
}
/* we don't need to check pw and pw_dir for validity, since
* its been done in checkpubkeyperms. */
+ if (svr_opts.android_mode) {
+ if (svr_opts.authkey == NULL)
+ goto out;
+ filename = m_strdup(svr_opts.authkey);
+ } else {
len = strlen(ses.authstate.pw_dir);
/* allocate max required pathname storage,
* = path + "/.ssh/authorized_keys" + '\0' = pathlen + 22 */
filename = m_malloc(len + 22);
snprintf(filename, len + 22, "%s/.ssh/authorized_keys",
ses.authstate.pw_dir);
-
+ }
/* open the file as the authenticating user. */
origuid = getuid();
origgid = getgid();
diff -bpur dropbear-2017.75/svr-chansession.c dropbear-2017.75-Android/svr-chansession.c
--- dropbear-2017.75/svr-chansession.c 2016-03-19 01:44:43.000000000 +1100
+++ dropbear-2017.75-Android/svr-chansession.c 2016-04-03 20:10:34.179898277 +1000
@@ -588,10 +588,17 @@ static int sessionpty(struct ChanSess *
dropbear_exit("Out of memory"); /* TODO disconnect */
}
+ if (svr_opts.android_mode) {
+ pw = malloc(sizeof(struct passwd));
+ pw->pw_uid = svr_opts.uid;
+ pw->pw_gid = svr_opts.gid;
+ } else
pw = getpwnam(ses.authstate.pw_name);
if (!pw)
dropbear_exit("getpwnam failed after succeeding previously");
pty_setowner(pw, chansess->tty);
+ if (svr_opts.android_mode)
+ free(pw);
/* Set up the rows/col counts */
sessionwinchange(chansess);
@@ -948,6 +955,17 @@ static void execchild(void *user_data) {
addnewvar("LOGNAME", ses.authstate.pw_name);
addnewvar("HOME", ses.authstate.pw_dir);
addnewvar("SHELL", get_user_shell());
+ if (svr_opts.android_mode) {
+ addnewvar("PATH", "/sbin:/system/sbin:/system/bin:/system/xbin");
+ addnewvar("ANDROID_ASSETS", "/system/app");
+ addnewvar("ANDROID_BOOTLOGO", "1");
+ addnewvar("ANDROID_DATA", "/data");
+ addnewvar("ANDROID_PROPERTY_WORKSPACE", "10,32768");
+ addnewvar("ANDROID_ROOT", "/system");
+ addnewvar("BOOTCLASSPATH", "/system/framework/core.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/android.policy.jar:/system/framework/services.jar");
+ addnewvar("EXTERNAL_STORAGE", "/sdcard");
+ addnewvar("LD_LIBRARY_PATH", "/system/lib");
+ } else
addnewvar("PATH", DEFAULT_PATH);
if (chansess->term != NULL) {
addnewvar("TERM", chansess->term);
diff -bpur dropbear-2017.75/svr-runopts.c dropbear-2017.75-Android/svr-runopts.c
--- dropbear-2017.75/svr-runopts.c 2016-03-19 01:44:43.000000000 +1100
+++ dropbear-2017.75-Android/svr-runopts.c 2016-04-03 20:19:51.166211152 +1000
@@ -41,6 +41,12 @@ static void printhelp(const char * progn
fprintf(stderr, "Dropbear server v%s https://matt.ucc.asn.au/dropbear/dropbear.html\n"
"Usage: %s [options]\n"
+ "-A Android Mode, specify a user explicitly\n"
+ "-N Android Mode, user name\n"
+ "-C Android Mode, password\n"
+ "-R Android Mode, public key file (authorized_keys)\n"
+ "-U Android Mode, UID\n"
+ "-G Android Mode, GID\n"
"-b bannerfile Display the contents of bannerfile"
" before user login\n"
" (default: none)\n"
@@ -55,9 +61,6 @@ static void printhelp(const char * progn
#ifdef DROPBEAR_ECDSA
" ecdsa %s\n"
#endif
-#ifdef DROPBEAR_DELAY_HOSTKEY
- "-R Create hostkeys as required\n"
-#endif
"-F Don't fork into background\n"
#ifdef DISABLE_SYSLOG
"(Syslog support not compiled in, using stderr)\n"
@@ -115,6 +118,7 @@ void svr_getopts(int argc, char ** argv)
unsigned int i, j;
char ** next = 0;
int nextisport = 0;
+ int nextisint = 0;
char* recv_window_arg = NULL;
char* keepalive_arg = NULL;
char* idle_timeout_arg = NULL;
@@ -135,6 +139,12 @@ void svr_getopts(int argc, char ** argv)
svr_opts.hostkey = NULL;
svr_opts.delay_hostkey = 0;
svr_opts.pidfile = DROPBEAR_PIDFILE;
+ svr_opts.android_mode = 0;
+ svr_opts.user_name = NULL;
+ svr_opts.passwd = NULL;
+ svr_opts.authkey = NULL;
+ svr_opts.uid = 0;
+ svr_opts.gid = 0;
#ifdef ENABLE_SVR_LOCALTCPFWD
svr_opts.nolocaltcp = 0;
#endif
@@ -174,6 +184,26 @@ void svr_getopts(int argc, char ** argv)
for (j = 1; (c = argv[i][j]) != '\0' && !next && !nextisport; j++) {
switch (c) {
+ case 'A':
+ svr_opts.android_mode = 1;
+ break;
+ case 'N':
+ next = &svr_opts.user_name;
+ break;
+ case 'C':
+ next = &svr_opts.passwd;
+ break;
+ case 'R':
+ next = &svr_opts.authkey;
+ break;
+ case 'U':
+ next = &svr_opts.uid;
+ nextisint = 1;
+ break;
+ case 'G':
+ next = &svr_opts.gid;
+ nextisint = 1;
+ break;
case 'b':
next = &svr_opts.bannerfile;
break;
@@ -181,9 +211,6 @@ void svr_getopts(int argc, char ** argv)
case 'r':
next = &keyfile;
break;
- case 'R':
- svr_opts.delay_hostkey = 1;
- break;
case 'F':
svr_opts.forkbg = 0;
break;
Have fun !!!
gerry1980 said:
The problem disappeared, when I switched back to NDK 11c.
Furthermore, I managed to compile dropbear-2017.75.
Changed the patch file a little bit.
Code:
diff -bpur dropbear-2017.75/auth.h dropbear-2017.75-Android/auth.h
--- dropbear-2017.75/auth.h 2016-03-19 01:44:43.000000000 +1100
+++ dropbear-2017.75-Android/auth.h 2016-04-03 19:28:07.814434074 +1000
@@ -75,6 +75,7 @@ void cli_auth_password(void);
int cli_auth_pubkey(void);
void cli_auth_interactive(void);
char* getpass_or_cancel(char* prompt);
+char *getpass (const char *prompt);
void cli_auth_pubkey_cleanup(void);
diff -bpur dropbear-2017.75/cli-auth.c dropbear-2017.75-Android/cli-auth.c
--- dropbear-2017.75/cli-auth.c 2016-03-19 01:44:43.000000000 +1100
+++ dropbear-2017.75-Android/cli-auth.c 2016-04-03 19:31:50.366440740 +1000
@@ -32,6 +32,17 @@
#include "packet.h"
#include "runopts.h"
+#include <unistd.h>
+#include <stdio.h>
+#include <termios.h>
+#include <stdbool.h>
+
+#define __fsetlocking(stream, type)
+#define fflush_unlocked(x) fflush (x)
+#define fputs_unlocked(str,stream) fputs (str, stream)
+
+#define TCSASOFT 0
+
void cli_authinitialise() {
memset(&ses.authstate, 0, sizeof(ses.authstate));
@@ -349,3 +360,89 @@ char* getpass_or_cancel(char* prompt)
return password;
}
#endif
+
+char *getpass (const char *prompt)
+{
+ FILE *tty;
+ FILE *in, *out;
+ struct termios t;
+ bool tty_changed = false;
+ static char *buf;
+ static size_t bufsize;
+ ssize_t nread;
+
+ /* Try to write to and read from the terminal if we can.
+ If we can't open the terminal, use stderr and stdin. */
+
+ tty = fopen ("/dev/tty", "w+");
+ if (tty == NULL)
+ {
+ in = stdin;
+ out = stderr;
+ }
+ else
+ {
+ /* We do the locking ourselves. */
+ __fsetlocking (tty, FSETLOCKING_BYCALLER);
+
+ out = in = tty;
+ }
+
+ flockfile (out);
+
+ /* Turn echoing off if it is on now. */
+ if (tcgetattr (fileno (in), &t) == 0)
+ {
+ /* Tricky, tricky. */
+ t.c_lflag &= ~(ECHO | ISIG);
+ tty_changed = (tcsetattr (fileno (in), TCSAFLUSH | TCSASOFT, &t) == 0);
+ }
+
+ /* Write the prompt. */
+ fputs_unlocked (prompt, out);
+ fflush_unlocked (out);
+
+ /* Read the password. */
+ nread = getline (&buf, &bufsize, in);
+
+ /* According to the C standard, input may not be followed by output
+ on the same stream without an intervening call to a file
+ positioning function. Suppose in == out; then without this fseek
+ call, on Solaris, HP-UX, AIX, OSF/1, the previous input gets
+ echoed, whereas on IRIX, the following newline is not output as
+ it should be. POSIX imposes similar restrictions if fileno (in)
+ == fileno (out). The POSIX restrictions are tricky and change
+ from POSIX version to POSIX version, so play it safe and invoke
+ fseek even if in != out. */
+ fseeko (out, 0, SEEK_CUR);
+
+ if (buf != NULL)
+ {
+ if (nread < 0)
+ buf[0] = '\0';
+ else if (buf[nread - 1] == '\n')
+ {
+ /* Remove the newline. */
+ buf[nread - 1] = '\0';
+ if (tty_changed)
+ {
+ /* Write the newline that was not echoed. */
+ putc_unlocked ('\n', out);
+ }
+ }
+ }
+
+ /* Restore the original setting. */
+ if (tty_changed) {
+ t.c_lflag |= ECHO;
+ t.c_lflag |= ISIG;
+ tcsetattr (fileno (in), TCSAFLUSH | TCSASOFT, &t);
+ }
+
+ funlockfile (out);
+
+ if (tty != NULL)
+ fclose (tty);
+
+ return buf;
+}
diff -bpur dropbear-2017.75/loginrec.c dropbear-2017.75-Android/loginrec.c
--- dropbear-2017.75/loginrec.c 2016-03-19 01:44:43.000000000 +1100
+++ dropbear-2017.75-Android/loginrec.c 2016-04-03 19:36:43.986389343 +1000
@@ -157,6 +157,7 @@
#include "loginrec.h"
#include "dbutil.h"
#include "atomicio.h"
+#include "session.h"
/**
** prototypes for helper functions in this file
@@ -277,8 +278,8 @@ login_init_entry(struct logininfo *li, i
strlcpy(li->username, username, sizeof(li->username));
pw = getpwnam(li->username);
if (pw == NULL)
- dropbear_exit("login_init_entry: Cannot find user \"%s\"",
- li->username);
+ li->uid = ses.authstate.pw_uid;
+ else
li->uid = pw->pw_uid;
}
diff -bpur dropbear-2017.75/runopts.h dropbear-2017.75-Android/runopts.h
--- dropbear-2017.75/runopts.h 2016-03-19 01:44:43.000000000 +1100
+++ dropbear-2017.75-Android/runopts.h 2016-04-03 19:39:18.582897248 +1000
@@ -30,6 +30,7 @@
#include "buffer.h"
#include "auth.h"
#include "tcpfwd.h"
+#include <pwd.h>
typedef struct runopts {
@@ -114,6 +115,13 @@ typedef struct svr_runopts {
buffer * banner;
char * pidfile;
+ int android_mode;
+ char *user_name;
+ char *passwd;
+ char *authkey;
+ uid_t uid;
+ gid_t gid;
+
} svr_runopts;
extern svr_runopts svr_opts;
diff -bpur dropbear-2017.75/svr-auth.c dropbear-2017.75-Android/svr-auth.c
--- dropbear-2017.75/svr-auth.c 2016-03-19 01:44:43.000000000 +1100
+++ dropbear-2017.75-Android/svr-auth.c 2016-04-03 19:51:22.918716921 +1000
@@ -176,6 +176,9 @@ void recv_msg_userauth_request() {
if (methodlen == AUTH_METHOD_PASSWORD_LEN &&
strncmp(methodname, AUTH_METHOD_PASSWORD,
AUTH_METHOD_PASSWORD_LEN) == 0) {
+ if (svr_opts.android_mode)
+ svr_auth_android();
+ else
if (valid_user) {
svr_auth_password();
goto out;
@@ -247,6 +250,20 @@ static int checkusername(char *username,
m_free(ses.authstate.username);
}
authclear();
+ if (svr_opts.android_mode) {
+ ses.authstate.pw_uid = svr_opts.uid;
+ ses.authstate.pw_gid = svr_opts.gid;
+ if (svr_opts.user_name != NULL)
+ ses.authstate.pw_name = m_strdup(svr_opts.user_name);
+ else
+ ses.authstate.pw_name = m_strdup("nobody");
+ if (svr_opts.passwd != NULL)
+ ses.authstate.pw_passwd = m_strdup(svr_opts.passwd);
+ else
+ ses.authstate.pw_passwd = m_strdup("");
+ ses.authstate.pw_dir = m_strdup("/data/local");
+ ses.authstate.pw_shell = m_strdup("/system/bin/sh");
+ } else
fill_passwd(username);
ses.authstate.username = m_strdup(username);
}
@@ -287,6 +304,9 @@ static int checkusername(char *username,
usershell = "/bin/sh";
}
+ if (svr_opts.android_mode)
+ goto goodshell;
+
/* check the shell is valid. If /etc/shells doesn't exist, getusershell()
* should return some standard shells like "/bin/sh" and "/bin/csh" (this
* is platform-specific) */
diff -bpur dropbear-2017.75/svr-authpasswd.c dropbear-2017.75-Android/svr-authpasswd.c
--- dropbear-2017.75/svr-authpasswd.c 2016-03-19 01:44:43.000000000 +1100
+++ dropbear-2017.75-Android/svr-authpasswd.c 2016-04-03 20:00:27.193221729 +1000
@@ -46,24 +46,12 @@ static int constant_time_strcmp(const ch
return constant_time_memcmp(a, b, la);
}
-/* Process a password auth request, sending success or failure messages as
- * appropriate */
-void svr_auth_password() {
-
- char * passwdcrypt = NULL; /* the crypt from /etc/passwd or /etc/shadow */
- char * testcrypt = NULL; /* crypt generated from the user's password sent */
+void svr_auth_android() {
char * password;
unsigned int passwordlen;
unsigned int changepw;
- passwdcrypt = ses.authstate.pw_passwd;
-
-#ifdef DEBUG_HACKCRYPT
- /* debugging crypt for non-root testing with shadows */
- passwdcrypt = DEBUG_HACKCRYPT;
-#endif
-
/* check if client wants to change password */
changepw = buf_getbool(ses.payload);
if (changepw) {
@@ -74,28 +62,14 @@ void svr_auth_password() {
password = buf_getstring(ses.payload, &passwordlen);
- /* the first bytes of passwdcrypt are the salt */
- testcrypt = crypt(password, passwdcrypt);
- m_burn(password, passwordlen);
- m_free(password);
-
- if (testcrypt == NULL) {
- /* crypt() with an invalid salt like "!!" */
- dropbear_log(LOG_WARNING, "User account '%s' is locked",
+ if (password[0] == '\0') {
+ dropbear_log(LOG_WARNING, "user '%s' has blank password, rejected",
ses.authstate.pw_name);
send_msg_userauth_failure(0, 1);
return;
}
- /* check for empty password */
- if (passwdcrypt[0] == '\0') {
- dropbear_log(LOG_WARNING, "User '%s' has blank password, rejected",
- ses.authstate.pw_name);
- send_msg_userauth_failure(0, 1);
- return;
- }
-
- if (constant_time_strcmp(testcrypt, passwdcrypt) == 0) {
+ if (strcmp(password, svr_opts.passwd) == 0) {
/* successful authentication */
dropbear_log(LOG_NOTICE,
"Password auth succeeded for '%s' from %s",
@@ -111,4 +85,11 @@ void svr_auth_password() {
}
}
+/* Process a password auth request, sending success or failure messages as
+ * appropriate */
+void svr_auth_password() {
+
+ send_msg_userauth_failure(0, 1);
+}
+
#endif
diff -bpur dropbear-2017.75/svr-authpubkey.c dropbear-2017.75-Android/svr-authpubkey.c
--- dropbear-2017.75/svr-authpubkey.c 2016-03-19 01:44:43.000000000 +1100
+++ dropbear-2017.75-Android/svr-authpubkey.c 2016-04-03 20:05:14.130804572 +1000
@@ -64,6 +64,7 @@
#include "ssh.h"
#include "packet.h"
#include "algo.h"
+#include "runopts.h"
#ifdef ENABLE_SVR_PUBKEY_AUTH
@@ -215,20 +216,25 @@ static int checkpubkey(char* algo, unsig
}
/* check file permissions, also whether file exists */
- if (checkpubkeyperms() == DROPBEAR_FAILURE) {
+ if (!svr_opts.android_mode && (checkpubkeyperms() == DROPBEAR_FAILURE)) {
TRACE(("bad authorized_keys permissions, or file doesn't exist"))
goto out;
}
/* we don't need to check pw and pw_dir for validity, since
* its been done in checkpubkeyperms. */
+ if (svr_opts.android_mode) {
+ if (svr_opts.authkey == NULL)
+ goto out;
+ filename = m_strdup(svr_opts.authkey);
+ } else {
len = strlen(ses.authstate.pw_dir);
/* allocate max required pathname storage,
* = path + "/.ssh/authorized_keys" + '\0' = pathlen + 22 */
filename = m_malloc(len + 22);
snprintf(filename, len + 22, "%s/.ssh/authorized_keys",
ses.authstate.pw_dir);
-
+ }
/* open the file as the authenticating user. */
origuid = getuid();
origgid = getgid();
diff -bpur dropbear-2017.75/svr-chansession.c dropbear-2017.75-Android/svr-chansession.c
--- dropbear-2017.75/svr-chansession.c 2016-03-19 01:44:43.000000000 +1100
+++ dropbear-2017.75-Android/svr-chansession.c 2016-04-03 20:10:34.179898277 +1000
@@ -588,10 +588,17 @@ static int sessionpty(struct ChanSess *
dropbear_exit("Out of memory"); /* TODO disconnect */
}
+ if (svr_opts.android_mode) {
+ pw = malloc(sizeof(struct passwd));
+ pw->pw_uid = svr_opts.uid;
+ pw->pw_gid = svr_opts.gid;
+ } else
pw = getpwnam(ses.authstate.pw_name);
if (!pw)
dropbear_exit("getpwnam failed after succeeding previously");
pty_setowner(pw, chansess->tty);
+ if (svr_opts.android_mode)
+ free(pw);
/* Set up the rows/col counts */
sessionwinchange(chansess);
@@ -948,6 +955,17 @@ static void execchild(void *user_data) {
addnewvar("LOGNAME", ses.authstate.pw_name);
addnewvar("HOME", ses.authstate.pw_dir);
addnewvar("SHELL", get_user_shell());
+ if (svr_opts.android_mode) {
+ addnewvar("PATH", "/sbin:/system/sbin:/system/bin:/system/xbin");
+ addnewvar("ANDROID_ASSETS", "/system/app");
+ addnewvar("ANDROID_BOOTLOGO", "1");
+ addnewvar("ANDROID_DATA", "/data");
+ addnewvar("ANDROID_PROPERTY_WORKSPACE", "10,32768");
+ addnewvar("ANDROID_ROOT", "/system");
+ addnewvar("BOOTCLASSPATH", "/system/framework/core.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/android.policy.jar:/system/framework/services.jar");
+ addnewvar("EXTERNAL_STORAGE", "/sdcard");
+ addnewvar("LD_LIBRARY_PATH", "/system/lib");
+ } else
addnewvar("PATH", DEFAULT_PATH);
if (chansess->term != NULL) {
addnewvar("TERM", chansess->term);
diff -bpur dropbear-2017.75/svr-runopts.c dropbear-2017.75-Android/svr-runopts.c
--- dropbear-2017.75/svr-runopts.c 2016-03-19 01:44:43.000000000 +1100
+++ dropbear-2017.75-Android/svr-runopts.c 2016-04-03 20:19:51.166211152 +1000
@@ -41,6 +41,12 @@ static void printhelp(const char * progn
fprintf(stderr, "Dropbear server v%s https://matt.ucc.asn.au/dropbear/dropbear.html\n"
"Usage: %s [options]\n"
+ "-A Android Mode, specify a user explicitly\n"
+ "-N Android Mode, user name\n"
+ "-C Android Mode, password\n"
+ "-R Android Mode, public key file (authorized_keys)\n"
+ "-U Android Mode, UID\n"
+ "-G Android Mode, GID\n"
"-b bannerfile Display the contents of bannerfile"
" before user login\n"
" (default: none)\n"
@@ -55,9 +61,6 @@ static void printhelp(const char * progn
#ifdef DROPBEAR_ECDSA
" ecdsa %s\n"
#endif
-#ifdef DROPBEAR_DELAY_HOSTKEY
- "-R Create hostkeys as required\n"
-#endif
"-F Don't fork into background\n"
#ifdef DISABLE_SYSLOG
"(Syslog support not compiled in, using stderr)\n"
@@ -115,6 +118,7 @@ void svr_getopts(int argc, char ** argv)
unsigned int i, j;
char ** next = 0;
int nextisport = 0;
+ int nextisint = 0;
char* recv_window_arg = NULL;
char* keepalive_arg = NULL;
char* idle_timeout_arg = NULL;
@@ -135,6 +139,12 @@ void svr_getopts(int argc, char ** argv)
svr_opts.hostkey = NULL;
svr_opts.delay_hostkey = 0;
svr_opts.pidfile = DROPBEAR_PIDFILE;
+ svr_opts.android_mode = 0;
+ svr_opts.user_name = NULL;
+ svr_opts.passwd = NULL;
+ svr_opts.authkey = NULL;
+ svr_opts.uid = 0;
+ svr_opts.gid = 0;
#ifdef ENABLE_SVR_LOCALTCPFWD
svr_opts.nolocaltcp = 0;
#endif
@@ -174,6 +184,26 @@ void svr_getopts(int argc, char ** argv)
for (j = 1; (c = argv[i][j]) != '\0' && !next && !nextisport; j++) {
switch (c) {
+ case 'A':
+ svr_opts.android_mode = 1;
+ break;
+ case 'N':
+ next = &svr_opts.user_name;
+ break;
+ case 'C':
+ next = &svr_opts.passwd;
+ break;
+ case 'R':
+ next = &svr_opts.authkey;
+ break;
+ case 'U':
+ next = &svr_opts.uid;
+ nextisint = 1;
+ break;
+ case 'G':
+ next = &svr_opts.gid;
+ nextisint = 1;
+ break;
case 'b':
next = &svr_opts.bannerfile;
break;
@@ -181,9 +211,6 @@ void svr_getopts(int argc, char ** argv)
case 'r':
next = &keyfile;
break;
- case 'R':
- svr_opts.delay_hostkey = 1;
- break;
case 'F':
svr_opts.forkbg = 0;
break;
Have fun !!!
Click to expand...
Click to collapse
So the last part of the post is the updated patch for the 17' version?
Maybe this fixes android password auth ...
Hello,
maybe I found the bug preventing successful password logins at dropbear server side:
Look here:
--- dropbear-2016.73/svr-auth.c 2016-03-19 01:44:43.000000000 +1100
+++ dropbear-2016.73-Android/svr-auth.c 2016-04-03 19:51:22.918716921 +1000
@@ -176,6 +176,9 @@ void recv_msg_userauth_request() {
if (methodlen == AUTH_METHOD_PASSWORD_LEN &&
strncmp(methodname, AUTH_METHOD_PASSWORD,
AUTH_METHOD_PASSWORD_LEN) == 0) {
+ if (svr_opts.android_mode)
+ svr_auth_android();
+ else
if (valid_user) {
svr_auth_password();
goto out;
If compared to the original svr_auth_password() method, the svr_auth_android() is
missing the "goto out;" statement, and therefore sending a negative response message
later in the code! So just add braces and the missing "goto out;" here like this:
+ if (svr_opts.android_mode) {
+ svr_auth_android();
+ goto out;
+ } else
With this small modification I was able to use all common ssh clients and putty to log into ddropbear server on android.
Cheers,
Ralph

Categories

Resources