Simplify password connections

This commit is contained in:
William Brawner 2020-02-05 07:17:02 -06:00
parent 1347b9ea10
commit e1c8ffcd5d
4 changed files with 14 additions and 48 deletions

View file

@ -6,15 +6,11 @@ import androidx.core.content.edit
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.wbrawner.piholeclient.PiHoleApiService
import com.wbrawner.piholeclient.Summary
import com.wbrawner.piholeclient.VersionResponse
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext
import java.net.ConnectException
import java.net.SocketTimeoutException
import java.util.regex.Pattern
import java.util.regex.Pattern.DOTALL
const val KEY_BASE_URL = "baseUrl"
const val KEY_API_KEY = "apiKey"
@ -56,7 +52,9 @@ class AddPiHelperViewModel(
suspend fun beginScanning(deviceIpAddress: String) {
val addressParts = deviceIpAddress.split(".").toMutableList()
var chunks = 1
val ipAddresses = mutableListOf<String>()
// If the Pi-hole is correctly set up, then there should be a special host for it as
// "pi.hole"
val ipAddresses = mutableListOf("pi.hole")
while (chunks <= IP_MAX) {
val chunkSize = (IP_MAX - IP_MIN + 1) / chunks
if (chunkSize == 1) {
@ -111,16 +109,8 @@ class AddPiHelperViewModel(
}
suspend fun authenticateWithPassword(password: String) {
// Perform the login to get the PHPSESSID cookie set
apiService.login(password)
val html = apiService.getApiToken()
val matcher = Pattern.compile(".*Raw API Token: ([a-z0-9]+).*", DOTALL)
.matcher(html)
if (!matcher.matches()) {
throw RuntimeException("Unable to retrieve API token from password")
}
val apiToken = matcher.group(1)!!
authenticateWithApiKey(apiToken)
// The Pi-hole API key is just the web password hashed twice with SHA-256
authenticateWithApiKey(password.hash().hash())
}
suspend fun authenticateWithApiKey(apiKey: String) {

View file

@ -1,3 +1,9 @@
package com.wbrawner.pihelper
fun <T, R> R.transform(block: (R) -> T): T = block(this)
import java.math.BigInteger
import java.security.MessageDigest
fun String.hash(): String = BigInteger(
1,
MessageDigest.getInstance("SHA-256").digest(this.toByteArray())
).toString(16)

View file

@ -15,12 +15,11 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import com.wbrawner.pihelper.MainActivity.Companion.ACTION_FORGET_PIHOLE
import kotlinx.android.synthetic.main.fragment_main.toolbar
import kotlinx.android.synthetic.main.fragment_info.*
import kotlinx.android.synthetic.main.fragment_main.toolbar
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import org.koin.android.ext.android.inject
import java.lang.RuntimeException
import kotlin.coroutines.CoroutineContext
class InfoFragment : Fragment(), CoroutineScope {
@ -30,7 +29,6 @@ class InfoFragment : Fragment(), CoroutineScope {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
throw RuntimeException("I crashed!")
}
override fun onCreateView(

View file

@ -4,20 +4,14 @@ import com.squareup.moshi.Moshi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.HttpUrl
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import kotlin.reflect.KClass
interface PiHoleApiService {
var baseUrl: String?
var apiKey: String?
suspend fun login(password: String): String
suspend fun getApiToken(): String
suspend fun getSummary(
version: Boolean = false,
type: Boolean = false
@ -48,8 +42,6 @@ interface PiHoleApiService {
}
const val BASE_PATH = "/admin/api.php"
const val INDEX_PATH = "/admin/index.php"
const val API_TOKEN_PATH = "/admin/scripts/pi-hole/php/api_token.php"
class OkHttpPiHoleApiService(
private val okHttpClient: OkHttpClient,
@ -110,26 +102,6 @@ class OkHttpPiHoleApiService(
return sendRequest(request.build(), TopItemsResponse::class)!!
}
override suspend fun login(password: String): String {
val url = urlBuilder
.encodedPath(INDEX_PATH)
.addQueryParameter("login", "")
val body = "pw=$password".toRequestBody("application/x-www-form-urlencoded".toMediaType())
val request = Request.Builder()
.post(body)
.url(url.build())
return sendRequest(request.build(), String::class)!!
}
override suspend fun getApiToken(): String {
val url = urlBuilder
.encodedPath(API_TOKEN_PATH)
val request = Request.Builder()
.get()
.url(url.build())
return sendRequest(request.build(), String::class)!!
}
override suspend fun enable(): StatusResponse {
val apiToken = this.apiKey ?: throw java.lang.IllegalStateException("No API Token provided")
val url = urlBuilder